Find nodes by edge and child node ids

Hi, I have a product <values> attributeOption relation.

Now I am trying to find all products having a values edge and fulfil this filter:

$and: [$in:{attributeOption.id, [10, 20]}, $in:{attributeOption.id, [30, 40]}]

Here is how I would do it in SQL with n-m relationship:

 SELECT count(*) from "products" 
 join "productValues" as v1 on "v1"."productId" =  "products"."id" and "v1"."optionId" in (10, 20)
 join "productValues" as v2 on "v2"."productId" =  "products"."id" and "v2"."optionId" in (30, 40)

How can I do this in Dgraph ? Thanks!

{
   "type": "product",
   "id": 1,
   "label": "Computer",
   "values": [
      {
         "type": "AttributeOption",
         "id": 20,
         "label": "Dell"
      },
      {
         "type": "AttributeOption",
         "id": 30,
         "label": "HP"
      },
      {
         "type": "AttributeOption",
         "id": 40,
         "label": "20Gb"
      },
      {
         "type": "AttributeOption",
         "id": 50,
         "label": "40Gb"
      }
   ]
}

Something like this?

{
  q(func: eq(label, "Computer")){
    id
    label
    values @filter(eq(id, ["10", "20", "30", "40"])) {
      id
      label
    }
  }
}

That was my first guess too but it’s not quite what I am looking for. Because it returns products that don’t match the filter.

Assuming this is my source:


const test = [
  {
    type: "product",
    id: 1,
    label: "Computer 1",
    values: [
      {
        type: "AttributeOption",
        id: 20,
        label: "Dell"
      },
      {
        type: "AttributeOption",
        id: 40,
        label: "20Gb"
      }
    ]
  },
  {
    type: "product",
    id: 2,
    label: "Computer 2",
    values: [
      {
        type: "AttributeOption",
        id: 30,
        label: "HP"
      },
      {
        type: "AttributeOption",
        id: 40,
        label: "20Gb"
      }
    ]
  }
]

I want to run two queres:

eq(type, ‘product’) and eq(values.id, [20, 30]) and eq(values.id, [40]) => this should return both products
eq(type, ‘product’) and eq(values.id, [30]) and eq(values.id, [40]) => this should return product with id 2

Hi @johnson, apologies for the delay. I hope you find this useful still.

Schema

id: int .
label: string .
values: [uid] @reverse .
type Product {
    id: int
    label: string
    values: [uid]
}
type AttributeOption {
    id: int
    label: string
}

Data

<1> <id> "1" .
<1> <label> "Computer 1" .
<1> <dgraph.type> "Product" .
        
<2> <id> "2" .
<2> <label> "Computer 2" .
<2> <dgraph.type> "Product" .

<3> <id> "20" .
<3> <label> "Dell" .
<3> <dgraph.type> "AttributeOption" .

<4> <id> "40" .
<4> <label> "20GB" .
<4> <dgraph.type> "AttributeOption" .

<5> <id> "30" .
<5> <label> "HP" .
<5> <dgraph.type> "AttributeOption" .

<1> <values> <3> .
<1> <values> <4> .
<2> <values> <5> .
<2> <values> <4> .

Queries:
For the first query, you can go with the below:

query{
    var(func: type(Product) ){
        v1 as values @filter( lt(id, 30) AND gt(id, 20) )
    }
    var(func: type(Product) ){
        v2 as values @filter( eq(id, 40)  )
    }
    q(func: uid(v1, v2)){
        ~values{
            id
            label
        }
    }
}

Edit: On looking closely at this, the above query works but that is more accidental. Taking a closer look.

Okay, Taking Anurag’s sample I have found the following.

query

query{

  G as var(func: type(Product) )
  
  G1 as var(func: uid(G) ) @cascade  {
    values @filter(eq(id, "40"))
  }
  G2 as var(func: uid(G) ) @cascade  {
    values @filter(eq(id, "30", "20"))
  }

  q(func: uid(G1, G2) )  {
    uid
    label
  }
}

Return

{
  "data": {
    "q": [
      {
        "uid": "0x1",
        "label": "Computer 1"
      },
      {
        "uid": "0x2",
        "label": "Computer 2"
      }
    ]
  }
}

query

query{

  G as var(func: type(Product) )

  q(func: uid(G) ) @cascade {
    uid
    label
    id
    values @filter( eq(id, "40", "30"))
  }
}

Return

{
  "data": {
    "q": [
      {
        "uid": "0x2",
        "label": "Computer 2",
        "id": 2
      }
    ]
  }
}
2 Likes

Didn’t know cascade could be used for child nodes as well, I thought only for scalar predicates. Great work! I learn so much from you @MichelDiz! :slight_smile:

1 Like