How to write a query simulating a very primitive recommendation system?

Hi,

I’d like to answer “Who bought this product also bought…” using a very simple e-commerce example.
I have the product UID and I’d like to get a unique list of other products sold together.

// schema
name: string @index(term) .
products: [uid] @reverse .

type Product {
    name
}

type Order {
    products: Product
}

// mutations
"set": [
    {
        "dgraph.type": "Product",
        "name": "Product 1"
    },
        {
        "dgraph.type": "Product",
        "name": "Product 2"
    },
        {
        "dgraph.type": "Product",
        "name": "Product 3"
    },
        {
        "dgraph.type": "Product",
        "name": "Product 4"
    },
        {
        "dgraph.type": "Product",
        "name": "Product 5"
    }
]

"set": [
    {
        "dgraph.type": "Order",
        "products": [ { "uid": "0x21" }, { "uid": "0x22" }]
    },
    {
        "dgraph.type": "Order",
        "products": [ { "uid": "0x21" }, { "uid": "0x23" }]
    },
    {
        "dgraph.type": "Order",
        "products": [ { "uid": "0x23" }, { "uid": "0x24" }]
    },
    {
        "dgraph.type": "Order",
        "products": [ { "uid": "0x21" }, { "uid": "0x22" }, { "uid": "0x23" }]
    }
]

It is the better query I thought:

// request
res(func: type(Order)) @cascade {
    products @filter(uid("0x21"))
    also_bought: products @filter(NOT uid("0x21")) {
        uid
        name
    }
}

// response
"q": [
    {
        "also_bought":[
            {
                "uid":"0x23",
                "name":"Product 3"
            }
        ]
    },
    {
        "also_bought":[
            {
                "uid":"0x22",
                "name":"Product 2"
            },
            {
                "uid":"0x23",
                "name":"Product 3"
            }
        ]
    },
    {
        "also_bought":[
            {
                "uid":"0x22",
                "name":"Product 2"
            }
        ]
    }
]

I’d like the response has Product 2 and Product 3 not duplicated.
Any idea about how to rewrite this query?

Try this.

{

  U1 as var(func: eq(name, "Product 1"))

  var(func: type(Order)) @cascade {
    products @filter(uid(U1))
      also_bought: products @filter(NOT uid(U1)) {
        G as uid
      }
    }

      also_bought(func: uid(G)) {
        name
      }
}

Modified dataset

{
   "set": [
      {
         "uid": "_:0x21",
         "dgraph.type": "Product",
         "name": "Product 1"
      },
      {
         "uid": "_:0x22",
         "dgraph.type": "Product",
         "name": "Product 2"
      },
      {
         "uid": "_:0x23",
         "dgraph.type": "Product",
         "name": "Product 3"
      },
      {
         "uid": "_:0x24",
         "dgraph.type": "Product",
         "name": "Product 4"
      },
      {
         "uid": "_:0x25",
         "dgraph.type": "Product",
         "name": "Product 5"
      },
      {
         "dgraph.type": "Order",
         "products": [
            {
               "uid": "_:0x21"
            },
            {
               "uid": "_:0x22"
            }
         ]
      },
      {
         "dgraph.type": "Order",
         "products": [
            {
               "uid": "_:0x21"
            },
            {
               "uid": "_:0x23"
            }
         ]
      },
      {
         "dgraph.type": "Order",
         "products": [
            {
               "uid": "_:0x23"
            },
            {
               "uid": "_:0x24"
            }
         ]
      },
      {
         "dgraph.type": "Order",
         "products": [
            {
               "uid": "_:0x21"
            },
            {
               "uid": "_:0x22"
            },
            {
               "uid": "_:0x23"
            }
         ]
      }
   ]
}

Nice, it worked!
Thank you so much!