精怪查询基于边缘性递归获取节点
问题描述:
考虑下面的示例数据,我想建立一个小鬼查询返回的红宝石连接Alice的网络,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相当陌生,我一直在困惑的几个食谱有我的理想查询共同的东西,但我仍然看不到如何到达那里...
非常感谢您提供的任何帮助或建议。
答
当问小鬼问题,它总是帮助那些试图回答,如果你提供可以轻松剪切和粘贴到小鬼控制台这样的样品图:
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线可能是不言自明 - 找到“爱丽丝”然后遍历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()
这条道路进入你想要的形式。它展开每条路径,然后通过查找“value”的边缘唯一属性过滤掉边缘,然后提取该属性,然后将值折叠回地图中每个值的列表。
谢谢Stephen!伟大的解决方案,以及很好的解释。 +100。 –