在向 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]]
跟随第 3 行emit()
可能是不言自明的 - 找到“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
您想要的结构。显然,如果“bobby”在树中出现两次,您最终会得到两个针对他的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()
路径操作为您想要的形式。它展开每条路径,然后通过查找“值”的仅边缘属性来过滤掉边缘,然后将其提取出来,然后将值折叠回地图中每个值的列表中。