Using @reverse in JSON syntax

I could not find in the documentation how to use @reverse edges using the JSON mutation syntax. I want to delete all nodes that are referenced by a particular node, not just the relations, also the nodes - and think that reverse edges might help me do that. But I am using JSON queries and not RDF and could not find any reference on what syntax that might have.

JSON syntax has only a single direction. So you can’t use the reverse index via JSON syntax. But it is easy to workaround it. You can use separated JSON objects in the body of the mutations with the UID (or blank node if you are creating new nodes) and the edge.

e.g:

You want to create a child node that has an incoming edge from a given pre-existing node. This parent node comes from an edge that uses a reverse index.

So your mutation template would be like

{
   "set": [
      {
         "uid": "0x1",
         "parent.child": {
            "name": "Bob"
         }
      }
   ]
}

So, as parent.child has a reverse index. You can just query for the child and expand the edge parent.child reversely.

You probably wanna do something like

{
   "set": [
      {
         "name": "Bob",
         "~parent.child": {
            "uid": "0x1"
         }
      }
   ]
}

But that syntax makes the parser hard to follow. As we use internally libs that are standardized with JSON standards. It could be supported, but it is a kind of “syntax sugar” as you can simply do what I have mentioned above.

And apparently you want to use this syntax with delete operations. This is even more complicated with this syntax. The first syntax I showed works perfectly for the use case you want to do.

Well, that’s easy.

This template you gonna delete the relation first and then the child

{
   "delete": [
      {
         "uid": "0x1",
         "parent.child": {
            "uid": "0x2"
         }
      },
      {
         "uid": "0x2"
      }
   ]
}

And this last one you also deletes the parent.

{
   "delete": [
      {
         "uid": "0x1",
         "parent.child": {
            "uid": "0x2"
         }
      },
      {
         "uid": "0x2"
      },
      {
         "uid": "0x1"
      }
   ]
}

With RDF is the same thing. There’s no reverse in RDF.

If you wanna know more about deeper things, read this discussion here

You can jump to the 5th comment, where I shared a way to do this via Upsert Block. Also the last comment of @pawan sharing his view as a core dev about the design of Dgraph.

I think that’s all.

Cheers.

1 Like

Thank you @MichelDiz

I couldn’t really understand from the upsert example in the GitHub issue how this can be done without reverse edges and in JSON syntax.

I also couldn’t understand your solution

You can use separated JSON objects in the body of the mutations with the UID (or blank node if you are creating new nodes) and the edge.

Should I create a predicate in the child node like:

 my_parent: uid(parent)

and then do the deletion based on that?

So I can just find all nodes of that type that have the parent uid and remove them (in my case).

Tried deleting nodes that have a certain predicate with a uid value pointing to the parent - and failed miserably.

Attempt #1

{
  query: `query {
    parents(func:type("Parent")) @filter(eq(name,"Bob")) { parentUID as uid }
    children(func:type("Child")) @filter(uid_in(parent, uid(parentUID))) { childUID as uid }
  }`,
  delete: [{
    'uid': 'uid(childUID)'
  }]
}

This throws the error

Only val/count/len allowed as function within another. Got: uid

Attempt #2

{
  query: `query {
    parents(func:type("Parent")) @filter(eq(name,"Bob")) { parentUID as uid }
    children(func:type("Child")) @filter(uid_in(parent, parentUID)) { childUID as uid }
  }`,
  delete: [{
    'uid': 'uid(childUID)'
  }]
}

This throws the error

Value "parentUID" in uid_in is not a number

Attempt #3

{
  query: `query {
    parents(func:type("Parent")) @filter(eq(name,"Bob")) { parentUID as uid }
    children(func:type("Child")) @filter(eq(parent, parentUID)) { childUID as uid }
  }`,
  delete: [{
    'uid': 'uid(childUID)'
  }]
}

This throws the error

Attribute parent is not valid scalar type while running: name:"eq" args:"parentUID"

Attempt #4

{
  query: `query {
    parents(func:type("Parent")) @filter(eq(name,"Bob")) { parentUID as uid }
  }`,
  delete: [{
    'dgraph.type': 'Child',
    'parent': 'uid(parentUID)'
  }]
}

This throws the error

UID must be present and non-zero while deleting edges.

I am out of ideas here … this is extremely frustrating.

After WEEKS of agonizing frustration with DGraph, I have finally found the holy grail of GraphQL+/- syntax that does what I need …

Attempt: OMG!

{
  query: 'query {
    parents(func:type("Parent")) @filter(eq(name,"Bob")) { parentUID as uid }
    childrenUIDs as children(func:type("Child")) @cascade { parent @filter(uid(parentUID)) }
  }',
  delete: [{
    'uid': 'uid(childrenUIDs)'
  }, {
    'uid': 'uid(parentUID)',
    'children': 'uid(childrenUIDs)'
  }]
}

This query removes both the relations of the chosen parent with their children as well as the children themselves.

Nice, glad it worked for you. I had no idea that you question was related to upsert block tho, I thought it was exclusively about reverse index. Next time please, add more info in the question so we can help you right away.

Cheers.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.