Combine elements with relation to each other in query

I have data represented as a List(CSV),
I parse this list and insert the elements(different Kind) into dgraph,
then I want to query Elements with a relation to each other.

Let me try to explain, Bottles and Caps with

  • brand: A, height: 10, bottleID: 1, type: bottle
  • brand: B, height: 12, bottleID: 2, type: bottle
  • brand: C, weight: 1, bottleID: 1, type: cap

I have following schema:

    brand: string @index(hash).
    bottleID: int @index(int) .
    weight: int.
    height: int.
    cap: [uid] @ reverse.

    type bottle {
        brand
        height
        bottleID
        cap
    }

    type cap {
        brand
        weight
        bottleID
    }

my elements are persisted as:

[{
  "dgraph.type": "bottle",
  "height":10,
  "bottleID":1,
  "brand": "A"
},
{
  "dgraph.type": "bottle",
  "height":12,
  "bottleID":2,
  "brand": "B"
},
{
  "dgraph.type": "cap",
  "weight":1,
  "bottleID":1,
  "brand": "C"
}]

what I want as query response for bottles:

[{
  "dgraph.type" : "bottle",
  "height":10,
  "brand": "A",
  "cap": {
    "dgraph.type" : "cap",
    "weight":1,
    "brand": "C"
  }
},
{
  "dgraph.type" : "bottle",
  "height":12,
  "brand": "B"
}]

to achive this I query:

{
  var (func: type("bottle")) {
               A as bottleID
                uid
  },
  caps(func: type("cap"), orderasc: bottleID)@filter(eq(bottleID,val(A))) {
    B as bottleID
    uid
  }, 
  bottles(func: type("bottle"), orderasc: bottleID) @filter(eq(bottleID,val(B))){
               bottleID
                uid
  }
}

this returns me

"caps": [{
  "bottleID": 1,
  "uid": "0x25185"
}],
"bottles": [{
  "bottleID": 1,
  "uid": "0x25183"
}]

then I iterate over the to lists and add:

{"set":[ {
  "uid": "0x25183",
  "cap" : {
    "uid": "0x25185"
  }
}]}

for each pair.

then I can query:

{
  bottles(func: type("bottle")) {
    brand,
    height,
    cap {
     brand
     weight
  }
  }
}

then I get what I want:

"bottles": [
  {
    "brand": "A",
    "height": 10,
    "cap": {
      "brand": "C",
      "weight": 1
    }
  },{
    "brand": "B",
    "height": 12
  }
]

How could I query this, without adding the relation for cap?

Hey @jukrut, welcome to the cosiest graph database community on the web.

I don’t quite get your question - are you asking if you can get to your end result without having to run

{"set":[ {
  "uid": "0x25183",
  "cap" : {
    "uid": "0x25185"
  }
}]}

Why would you not want to add the relation? That is the strong point for using dgraph. If you don’t want to make the edges, a rdbs might be better where it allows you to do joins. But still… why don’t you want to add the edge?

correct, I would like to skip that step.

Why? because I have to add it,
I get lots of data, streamed to me so I have multiple nodes inserting into dgraph.

My current setup is 10 nodes inserting data without the links, and 2 nodes linking the pairs.
My example given is just an abstraction, in reallife I have 20 kind of different elements, with multiple links to each other, this is why graphdb seems a good fit.

OK, so at least I know I’m not doing it totally wrong :slight_smile:

Is there a way to make a combined query/mutation to add the links?
I could not do that… that would save me at least 1 step.
https://dgraph.io/docs/mutations/upsert-block/

Oh cool,
figured it out. Thx for the answers!

upsert {
  query {
    
  var (func: type("bottle")) {
               A as bottleID
                uid
  },
  caps(func: type("cap"), orderasc: bottleID)@filter(eq(bottleID,val(A))) {
    B as bottleID
    C as uid
  }, 
  bottles(func: type("bottle"), orderasc: bottleID) @filter(eq(bottleID,val(B))){
               bottleID
                D as uid
  }

  }

  mutation {
    set {
      uid(D) <test> uid(C) .
    }
  }
}

I’ll do a performance test,
currently I add 100 elements at once, and link them afterwards.

Maybe I’ll try to do this with an upsert at first, when inserting the cap, look for the bottle, and vice versa.