DQL upsert question

Hello

When using live loader, reverse edges are not set if not included in the JSON files.

So we are trying to run a DQL logic that sets the reverse edges afterwards

Schema:
type Item {
  id: ID!
  # Category
  category: Category
  ...
}

type Category {
  id: ID!
  categoryCode: String! @search(by: [term])
  items: [Item]  @hasInverse(field: "category")
  ...
}

This is the code:

curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
upsert {
  query {
    items(func: type(Item)) @normalize {
      itemUid as uid
      Item.category {      
        categoryUid as uid
      }  
    }
  }
  mutation {
    set {
      uid(categoryUid) <Category.items> uid(itemUid) .
    }
  }
}' | jq

Current dataset:

{
  "data": {
    "queryItem": [
      {
        "id": "0x4e3b",
        "itemNo": "Sky Wing 5.4",
        "category": {
          "id": "0x4e30",
          "categoryCode": "boards"
        }
      },
      {
        "id": "0x1117c",
        "itemNo": "Maui Cloud 6.2",
        "category": {
          "id": "0x4e30",
          "categoryCode": "boards"
        }
      },
      {
        "id": "0x7c86d",
        "itemNo": "watch-serialno",
        "category": {
          "id": "0x6ddd3",
          "categoryCode": "Watches"
        }
      },
      {
        "id": "0x7ef5e",
        "itemNo": "iphone-7-plus",
        "category": {
          "id": "0x7ef5b",
          "categoryCode": "Phones"
        }
      }
    ]
  },

Result after running the DQL above.

{
  "data": {
    "queryCategory": [
      {
        "id": "0x4e30",
        "categoryCode": "boards",
        "items": [
          {
            "id": "0x4e3b",
            "description": "Fanatic Sky Wing board 5.4"
          },
          {
            "id": "0x1117c",
            "description": "Maui Cloud kite Series E 6.2"
          },
          {
            "id": "0x7c86d",
            "description": "Hand made exclusive watch"
          },
          {
            "id": "0x7ef5e",
            "description": "iPhone 7 Plus"
          }
        ]
      },
      {
        "id": "0x6ddd3",
        "categoryCode": "Watches",
        "items": [
          {
            "id": "0x4e3b",
            "description": "Fanatic Sky Wing board 5.4"
          },
          {
            "id": "0x1117c",
            "description": "Maui Cloud kite Series E 6.2"
          },
          {
            "id": "0x7c86d",
            "description": "Hand made exclusive watch"
          },
          {
            "id": "0x7ef5e",
            "description": "iPhone 7 Plus"
          }
        ]
      },
      {
        "id": "0x7ef5b",

The desired results is not achieved. I tried different ways, but I could not find a way to set the variable containing the items uids per category. So the result is that all items are set to the categories …

Thanks

Regards

First, you don’t need a normalize directive in an Upsert Query. It has no use in that context. Also, it might mess up with things in the variables. As it might flat the nested nodes and be catched by the itemUid variable. That’s a theory based on that directive behavior.

Second thing is that this will get everything in item.category and link to itemUID without any distinction. You should not do such a wide query without careful logic behind it. Also, variables in Dgraph aren’t 1:1 based. It will collect all uids and set them all. If you wanna 1 to 1 link/connection. You should do a controlled query. Which is a “1:1 query” instead of a “many to many” case which is yours.

To control it, you have to send an upsert query per case or control it via pagination. e.g:

curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
upsert {
  query {
    items(func: type(Item), first:1, offset:0)  {
      itemUid as uid
      Item.category {      
        categoryUid as uid
      }  
    }
  }
  mutation {
    set {
      uid(categoryUid) <Category.items> uid(itemUid) .
    }
  }
}' | jq

And you send more queries changing the values in first:1, offset:X. You can use a wider query in cases you wanna indeed connect everything.