2

我有一个Neo4j Cypher查询。我试图了解如何在Tinkerpop/ Gremlin(不是Neo4j实现)中执行相同的查询。

start
  f=node:node_auto_index('_Element:field OR _Element:dynamicField'),
  t=node:node_auto_index(_Element = 'fieldType')
where
  f.type=t.name
return
  f, t

基本上,我得到两种类型的节点(标签/类型/其他),并尝试通过属性值匹配找到一个指向另一个的位置。然后,我将使用结果创建一个真实的关系。

图不是很大,最多几千个节点。

4

1 回答 1

2

与任何事情一样,有很多方法可以解决这个问题。由于您有一个小数据集,我认为g.V在 Gremlin 管道中进行查找不会有问题。为了模拟您的问题,我创建了自己的问题:使用玩具图,将sameFirstLetter边添加到具有lang属性的任何顶点到具有age属性并且它们各自name属性的第一个字母相同的任何顶点。在这种情况下,它应该添加两个顶点,从 5 到 4 和从 3 到 4。

gremlin> g = TinkerGraphFactory.createTinkerGraph()                                                                  
==>tinkergraph[vertices:6 edges:6]
gremlin> g.V.has('lang').transform{v->[v,g.V.has('age').filter{it.name.startsWith(v.lang[0])}.toList()]}.sideEffect{edgeList->edgeList[1].each{it.each{edgeList[0].addEdge('sameFirstLetter',it)}}}
==>[v[3], [v[4]]]
==>[v[5], [v[4]]]
gremlin> g.E
==>e[1][5-sameFirstLetter->4]
==>e[10][4-created->5]
==>e[0][3-sameFirstLetter->4]
==>e[7][1-knows->2]
==>e[9][1-created->3]
==>e[8][1-knows->4]
==>e[11][4-created->3]
==>e[12][6-created->3]

这段代码有两部分。第一个构造匹配的邻接列表,第二个创建边缘。这是获取邻接列表的部分:

g.V.has('lang').transform{v->[v,g.V.has('age').filter{it.name.startsWith(v.lang[0])}.toList()]}

上面的代码基本上是说,获取所有具有lang属性的顶点(请注意,此使用has是最新版本 Gremlin 的一部分 - 即将发布 2.4.0。在 2.4.0 之前,您可以执行.hasNot('lang',null)或类似操作)和然后将它们转换为一个列表,其中列表中的第一项是lang顶点,列表中的第二项是图中的第一个字母name与第一个字母匹配的顶点列表lang(在本例中j为两个lang顶点)。

.sideEffect{edgeList->edgeList[1].each{it.each{edgeList[0].addEdge('sameFirstLetter',it)}}}

上面的 sideEffect 正在处理这个输出......邻接列表:

==>[v[3], [v[4]]]
==>[v[5], [v[4]]]

此操作可以作为单独的代码行执行(并非所有 Gremlin 都需要编写在一行中……尽可能令人满意)。您可以简单地将邻接列表存储到一个变量中,然后对其进行后处理以创建边缘。在任何情况下,我都选择在sideEffect这里使用,在这里我循环创建边的列表列表。

或者,您还可以通过建立一个以属性值为键的内存索引来对数据集进行两次遍历,然后将其用作查找来构建邻接列表。这样,您将只需要通过顶点列表两次:

gremlin> m=g.V.groupBy{it.name[0]}{it}.cap.next()
==>v=[v[2]]
==>r=[v[5]]
==>p=[v[6]]
==>l=[v[3]]
==>m=[v[1]]
==>j=[v[4]]
gremlin> g.V.has('lang').transform{[it,m[it.lang[0]]]}
==>[v[3], [v[4]]]
==>[v[5], [v[4]]]

这将使您进入与上一个示例中相同的邻接列表。通过邻接列表创建边缘仍然如前所述执行。

于 2013-07-09T10:48:56.397 回答