反向边 (reverse edges)

Dgraph中的任何出边(outgoing edge)都可以使用Schema中的@reverse指令反向,并使用波浪号作为边名的前缀来查询。例如<~myEdge>

Dgraph是有向图模型,这意味着所有属性总是在一个方向上从一个实体指向另一个实体或值,即S P -> O

反向边是自动生成的边,不属于你的数据集的一部分。这意味着您不能直接在反向边上提交变更。改变正向边将会自动更新反向边的值。

正确地使用反向边

RDF中,三元组的排列已经定义了可以逆转的内容:

_:MyObject <myEdge> _:BlankNode  . #反向边正确的语法
_:BlankNode <dgraph.type> "Person" .

纠正和应用反向边的最简单方法是使用JSON。它只是将Schema上的指令放在所需的边上。在构建你的变更时,请记住JSON中没有反向边相关的语法。因此,您应该做的事情与RDF类似:更改JSON对象的排列。

因为MyObject实体在Person实体之上,所以在格式化变更时,MyObject必须在前面:

{
   "set": [
      {
         "uid": "_:MyObject",
         "dgraph.type": "Object",
         "myEdge": {
            "uid": "_:BlankNode",
            "dgraph.type": "Person"
         }
      }
   ]
}

另一种方法是分割成一些小块或小批,并使用空白节点作为引用。这有助于组织和重用引用:

{
   "set": [
      {
         "uid": "_:MyObject",
         "dgraph.type": "Object",
         "myEdge": [{"uid": "_:BlankNode"}]
      },
      {
         "uid": "_:BlankNode",
         "dgraph.type": "Person"
      }
   ]
}

更多的关于反向边的小例子

RDF中,想要正确地使用反向边非常简单:

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") .
  }
}

边的方向应该如下:

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") .

查询

  1. wife_husbandwife的反向边。
  2. husband是一条正常的正向边。
{
  q(func: has(wife)) {
    name
    WF as wife {
      name
    }
  }
  reverseIt(func: uid(WF)) {
    name
    wife_husband : ~wife {
      name
    }
    husband {
      name
    }
  }
}
  1. Childrenparent 的反向边:
{
  q(func: has(name)) @filter(eq(name, "Earl Sneed Sinclair")){
    name
    Children : ~parent @facets {
      name
    }
  }
}

反向边和 facet

反向边上的facet与正向边上的相同。也就是说,如果您在一条边上设置或更新一个facet,那么它的反向边将具有相同的facet

{
  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") .
  }
}

使用前面例子中的类似查询:

{
  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"
          }
        ]
      }
    ]
  }
}