Ask a Question Reverse Edges Any outgoing edge in Dgraph can be reversed using the @reverse directive in the schema and be queried using tilde as the prefix of the edge name. e.g. <~myEdge>. Dgraph serializes directed graphs. This means that all properties always point from an entity to another entity or value in a single direction. S P -> O. Reverse edges are automatically generated edges and are not part of your dataset. This means that you cannot run mutations directly on the reverse edges. Mutating the forward edge will automatically update the reverse edge. Using Reverse Edges correctly In RDF the arrangement of the triples already defines what can be reversed. _:MyObject <myEdge> _:BlankNode . #That's the right syntax of a reverse edge. _:BlankNode <dgraph.type> "Person" . The easiest way to correct and apply reverse edges is using JSON. It is simply having the directive on schema at the desired edge. When building your mutations remember that there is no reverse syntax in JSON. So what you should do is similar to RDF: change the arrangement of the JSON objects. Since MyObject is above the Person entity, MyObject must come before when formatting the mutation. { "set": [ { "uid": "_:MyObject", "dgraph.type": "Object", "myEdge": { "uid": "_:BlankNode", "dgraph.type": "Person" } } ] } Another way to do this is to separate into small chunks/batches and use blank nodes as references. This facilitates the organization and reuse of references. { "set": [ { "uid": "_:MyObject", "dgraph.type": "Object", "myEdge": [{"uid": "_:BlankNode"}] }, { "uid": "_:BlankNode", "dgraph.type": "Person" } ] } More reverse examples In RDF the correct way to apply reverse edges is very straight-forward. name: String . husband: uid @reverse . wife: uid @reverse . parent: [uid] @reverse . { set { _:Megalosaurus <name> "Earl Sneed Sinclair" . _:Megalosaurus <dgraph.type> "Dinosaur" . _:Megalosaurus <wife> _:Allosaurus . _:Allosaurus <name> "Francis Johanna Phillips Sinclair" (short="Fran") . _:Allosaurus <dgraph.type> "Dinosaur" . _:Allosaurus <husband> _:Megalosaurus . _:Hypsilophodon <name> "Robert Mark Sinclair" (short="Robbie") . _:Hypsilophodon <dgraph.type> "Dinosaur" . _:Hypsilophodon <parent> _:Allosaurus (role="son") . _:Hypsilophodon <parent> _:Megalosaurus (role="son") . _:Protoceratops <name> "Charlene Fiona Sinclair" . _:Protoceratops <dgraph.type> "Dinosaur" . _:Protoceratops <parent> _:Allosaurus (role="daughter") . _:Protoceratops <parent> _:Megalosaurus (role="daughter") . _:MegalosaurusBaby <name> "Baby Sinclair" (short="Baby") . _:MegalosaurusBaby <dgraph.type> "Dinosaur" . _:MegalosaurusBaby <parent> _:Allosaurus (role="son") . _:MegalosaurusBaby <parent> _:Megalosaurus (role="son") . } } The directions are like: Exchanged hierarchy: Object -> Parent; Object <~ Parent; #Reverse Children to parents via "parent" edge. wife and husband bidirectional using reverse. Normal hierarchy: Parent -> Object; Parent <~ Object; #Reverse This hierarchy is not part of the example, but is generally used in all graph models. To make this hierarchy we need to bring the hierarchical relationship starting from the parents and not from the children. Instead of using the edges "wife" and "husband" we switch to single edge called "married" to simplify the model. _:Megalosaurus <name> "Earl Sneed Sinclair" . _:Megalosaurus <dgraph.type> "Dinosaur" . _:Megalosaurus <married> _:Allosaurus . _:Megalosaurus <parent> _:Hypsilophodon (role="son") . _:Megalosaurus <parent> _:Protoceratops (role="daughter") . _:Megalosaurus <parent> _:MegalosaurusBaby (role="son") . _:Allosaurus <name> "Francis Johanna Phillips Sinclair" (short="Fran") . _:Allosaurus <dgraph.type> "Dinosaur" . _:Allosaurus <married> _:Megalosaurus . _:Allosaurus <parent> _:Hypsilophodon (role="son") . _:Allosaurus <parent> _:Protoceratops (role="daughter") . _:Allosaurus <parent> _:MegalosaurusBaby (role="son") . Queries wife_husband is the reversed wife edge. husband is an actual edge. { q(func: has(wife)) { name WF as wife { name } } reverseIt(func: uid(WF)) { name wife_husband : ~wife { name } husband { name } } } Children is the reversed parent edge. { q(func: has(name)) @filter(eq(name, "Earl Sneed Sinclair")){ name Children : ~parent @facets { name } } } Reverse Edges and Facets Facets on reverse edges are the same as the forward edge. That is, if you set or update a facet on an edge, its reverse will have the same facets. { set { _:Megalosaurus <name> "Earl Sneed Sinclair" . _:Megalosaurus <dgraph.type> "Dinosaur" . _:Megalosaurus <wife> _:Allosaurus . _:Megalosaurus <parent> _:MegalosaurusBaby (role="parent -> child") . _:MegalosaurusBaby <name> "Baby Sinclair" (short="Baby -> parent") . _:MegalosaurusBaby <dgraph.type> "Dinosaur" . _:MegalosaurusBaby <parent> _:Megalosaurus (role="child -> parent") . } } Using a similar query from the previous example: { Parent(func: has(name)) @filter(eq(name, "Earl Sneed Sinclair")){ name C as Children : parent @facets { name } } Child(func: uid(C)) { name parent @facets { name } } } { "data": { "Parent": [ { "name": "Earl Sneed Sinclair", "Children": [ { "name": "Baby Sinclair", "Children|role": "parent -> child" } ] } ], "Child": [ { "name": "Baby Sinclair", "parent": [ { "name": "Earl Sneed Sinclair", "parent|role": "child -> parent" } ] } ] } } ← Conditional Upsert