Correct usage of xid to upsert with Live uploader

Is below the right way to use xid to upsert with Live loader?

  1. My Model
   type Student {
    studentId: String! @id
    courses: [Course] @hasInverse(field: student)
    xid: String!  @search(by: [hash])
   }

   type Course {
    codeId: CourseTcode!
    eventId: Int!
    timestamp: DateTime! @search
    student: Student
    xid: String! @search(by: [hash])
   }

   type CourseTcode {
    codeConceptId: Int! @id
    course: Course @hasInverse(field: codeId)
    xid: String! @search(by: [hash])
   }
  1. 1st mutation
     <_:my.org/Student/10101> <Student.studentId> "10101" .
    
  2. 2nd mutation
    <_:my.org/CourseTcode/201> <CourseTcode.codeConceptId> "201" .
    
  3. 3rd mutation
   <_:my.org/Student/10101/Course/201/Event/1> <Course.eventId> "1" .
   <_:my.org/Student/10101/Course/201/Event/1> <Course.timestamp> "2022-01-01T00:00:02.298240" .
   <_:my.org/Student/10101/Course/201/Event/1> <Course.student> 
   <_:my.org/Student/10101> .
   <_:my.org/Student/10101> <Student.courses> 
   <_:my.org/Student/10101/Course/201/Event/1> .
   <_:my.org/Student/10101/Course/201/Event/1> <Course.codeId> 
   <_:my.org/CourseTcode/201> .
   <_:my.org/CourseTcode/201> <CourseTcode.course> 
   <_:my.org/Student/10101/Course/201/Event/1> .
1 Like

Feels okay, what are the issues?

Thanks for the reply @MichelDiz

I’m not able to get xid when I query for any of the 3 nodes.

What flags are you using in Live Loader? Share the query too.

Below is the exact command I’m using

dgraph live --files /root/dgraph/data --schema /root/dgraph/schema/my_schema.rdf --alpha dgraph-alpha:9080 --zero dgraph-zero:5080 --format=rdf --upsertPredicate "xid" -b 1500
1 Like

I never could get this to work and never tried again. It should allow you to use the same blank nodes later on.

I first notice that if you are trying to get the xid predicate surfaced in GraphQL then you have to map it with @dgraph(pred: "xid")

I’m using DQL through Ratel.

Below is my mapping…

<xid>: string @index(hash) .
<Student.studentId>: string @index(hash) @upsert .
<Student.courses>: [uid] @count .
<Student.xid>: string @index(hash) .

<Course.codeId>: uid .
<Course.eventId>: int .
<Course.student>: uid .
<Course.timestamp>: datetime @index(year) .
<Course.xid>: string @index(hash) .

<CourseTcode.codeConceptId>: int @index(int) @upsert .
<CourseTcode.course>: uid .
<CourseTcode.xid>: string @index(hash) .

Your usage seems correct to me. I’ve successfully used this but with the JSON format.

Using this as my input

{
  “uid”: “_:xid1”,
  “foo”: “bar”
}

with the —upsertPredicate “xid” flag, results in a node like

{
  “uid”: 0x001,
  “xid”: “_:xid1”,
  “foo”: “bar”
}

The upsert predicate should have a hash index (which you seem to have correctly set).

What does your query look like when you to try and get the xid for these nodes? Does running Live Loader multiple times with your arguments result in duplicates or is the upsert behavior being executed correctly?

My query is simple & straight forward

{
 test(func: has(Student.courses), first:5) {
  Student.studentId
  Student.xid
 }
}

Let me try to point this out again…

{
 test(func: has(Student.courses), first:5) {
  Student.studentId
  Student.xid # <-- Notice this
 }
}

compared with this:

<xid>: string @index(hash) . # <-- Not the same thing as
<Student.studentId>: string @index(hash) @upsert .
<Student.courses>: [uid] @count .
<Student.xid>: string @index(hash) . # <-- this here

<Course.codeId>: uid .
<Course.eventId>: int .
<Course.student>: uid .
<Course.timestamp>: datetime @index(year) .
<Course.xid>: string @index(hash) .

<CourseTcode.codeConceptId>: int @index(int) @upsert .
<CourseTcode.course>: uid .
<CourseTcode.xid>: string @index(hash) .

But in the command you are using:

dgraph live --files /root/dgraph/data --schema /root/dgraph/schema/my_schema.rdf --alpha dgraph-alpha:9080 --zero dgraph-zero:5080 --format=rdf --upsertPredicate "xid" -b 1500

In your command you use the predicate xid that is not the same as the Student.xid.

1 Like

Anthony nailed it. The predicate you specify in your flag will be used “as is” try this query instead:

{
 test(func: has(Student.courses), first:5) {
  Student.studentId
  xid
 }
}
  • Are you saying, I should use --upsertPredicate “Student.xid”?
  • If yes, I should run the upsert command once for each type?

You could run an upsert command for each type as stated above and then you’d have a <type>.xid predicate for each of your types.

However, the more practical approach would be to continue using xid as your upsertPredicate and expect each type to have an xid predicate (without the type prefix).

This works

<Student.xid>: string @index(hash) . # ← should I remove this then?

I would remove the Student.xid preds and map the GraphQL xid fields using the @dgraph directive so all types can share a single predicate that is then universally unique with live/bulk loading.

@amaster507 is does not upsert as expected for me, it creates duplicates

Can you share the steps you are taking with code snippets in case it varies from the other users above. Also what version are you using? I believe some changes were made between versions slightly to at least the run commands.