Gremlin 查询,用于根据边缘属性递归获取节点



给定以下示例数据,我想构造一个 Gremlin 查询,该查询返回 Alice 的 Ruby 连接网络,深度为 3 级:

Vertex: Alice
Vertex: Bobby
Vertex: Cindy
Vertex: David
Vertex: Eliza
Edge: [Alice] -> [Rates(tag:ruby,value:0.9)] -> [Bobby]
Edge: [Bobby] -> [Rates(tag:ruby,value:0.8)] -> [Cindy]
Edge: [Cindy] -> [Rates(tag:ruby,value:0.7)] -> [David]
Edge: [David] -> [Rates(tag:ruby,value:0.6)] -> [Eliza]   # ignored, level 4
Edge: [Alice] -> [Rates(tag:java,value:0.9)] -> [Eliza]   # ignored, not ruby

因此,返回的数据应该是这样的:

Bobby: [0.9]
Cindy: [0.9, 0.8]
David: [0.9, 0.8, 0.7]

返回每个顶点 ID 的位置,以及评级值路径的数组。

我正在当前版本的JanusGraph(Gremlin 3(中工作。我对小精灵很陌生;我一直对一些食谱感到困惑,这些食谱与我想要的查询有共同之处,但我仍然不知道如何到达那里......

非常感谢您提供的任何帮助或建议。

在询问 Gremlin 问题时,如果您提供一个可以轻松剪切并粘贴到 Gremlin 控制台中的示例图表,那么对于那些试图回答的人总是有帮助的,如下所示:

graph = TinkerGraph.open()
g = graph.traversal()
g.addV().property('name','alice').as('a').
addV().property('name','bobby').as('b').
addV().property('name','cindy').as('c').
addV().property('name','david').as('d').
addV().property('name','eliza').as('e').
addE('rates').property('tag','ruby').property('value',0.9).from('a').to('b').
addE('rates').property('tag','ruby').property('value',0.8).from('b').to('c').
addE('rates').property('tag','ruby').property('value',0.7).from('c').to('d').
addE('rates').property('tag','ruby').property('value',0.6).from('d').to('e').
addE('rates').property('tag','java').property('value',0.9).from('a').to('e').iterate()

使用这个图,我想出了这种方法来获得你想要的结果:

gremlin> g.V().has('name','alice').
......1>   repeat(outE().has('tag','ruby').inV()).
......2>     times(3).
......3>     emit().
......4>   group().
......5>     by('name').
......6>     by(path().
......7>        unfold().
......8>        has('value').
......9>        values('value').
.....10>        fold())
==>[bobby:[0.9],cindy:[0.9,0.8],david:[0.9,0.8,0.7]]

emit()跟进第 3 行可能是不言自明的 - 找到"alice",然后反复遍历out()到 3 的深度,并发出沿途发现的每个顶点。这让你得到你关心的顶点:

gremlin> g.V().has('name','alice').
......1>   repeat(outE().has('tag','ruby').inV()).
......2>     times(3).
......3>     emit()
==>v[2]
==>v[4]
==>v[6]

更复杂的部分是在此之后,您关心的是检索每个路径信息,以便您可以沿每个"速率"边缘获取"值"属性。我选择使用group以便可以轻松获得您想要的Map结构。显然,如果"鲍比"在树中出现两次,你最终会得到他的Map条目的两个评级列表。

如果你把group()中发生的事情分开,你可以看到它是由两个by()选项调制的。第一个对应于Map中的键(显然,我假设"名称"是唯一性的(。第二个从当前遍历器(人员顶点(中提取路径。在进一步之前,请先看看仅使用path()输出的外观:

gremlin> g.V().has('name','alice').
......1>   repeat(outE().has('tag','ruby').inV()).
......2>     times(3).
......3>     emit().
......4>   group().
......5>     by('name').
......6>     by(path()).next()
==>bobby=[v[0], e[10][0-rates->2], v[2]]
==>cindy=[v[0], e[10][0-rates->2], v[2], e[11][2-rates->4], v[4]]
==>david=[v[0], e[10][0-rates->2], v[2], e[11][2-rates->4], v[4], e[12][4-rates->6], v[6]]

下面的步骤path()将该路径操作成所需的表单。 它展开每条路径,然后通过查找"value"的"仅边缘"属性来过滤掉边缘,然后提取该属性,然后将值折叠回映射中每个值的列表中。

最新更新