Gremlin Big Pi操作(一系列术语的产物),然后是基于id的求和

时间:2013-12-08 15:09:24

标签: graph-databases gremlin tinkerpop

我有一个看起来像这样的数据集:

V1 = name:"some name1"
V2 = name:"some name2"
V3 = name:"some name3"
V4 = name:"some name4"

E1 = weight:0.2, StartVertex:V1, EndVertex:V2
E2 = weight:0.3, StartVertex:V1, EndVertex:V3
E3 = weight:0.4, StartVertex:V1, EndVertex:V4
E4 = weight:0.5, StartVertex:V2, EndVertex:V1
E5 = weight:0.6, StartVertex:V2, EndVertex:V3
...

我有一个gremlin查询,可以找到这些顶点之间的一些路径。

我想在那里做两件事。

  

1:我希望能够找到所有重量的产品   path(path_edge1.weight * path_edge2.weight * ...)

     

2:我希望能够为每条路径求和产品   基于末端顶点。

我希望实现的伪代码:

g.V().has('name',REGEX,\".+some_query.+\").inE.outV.inE.FindingAPathSomehow.path{path_score = 1 : foreach edge e: path_score = path_score * e.weight}{it.lastV().id}.sumWhereIdIsEqual(it[1])

希望这有点可以理解。

我希望能够在纯粹的gremlin / groovy脚本中完成所有操作,因为我使用的是RexPro。

我已经看了很多答案,但还没找到办法做到这一点。


进一步解释如果上述内容不清楚:

查询时我正在寻找子串等于“some_query”的顶点。这将给我一组起始顶点。

使用这些顶点,我在我的图表中寻找一条特定的路径,它会给我几条路径,看起来像这样:

V = Vertex
E = Edge

Path1 = V3 - E2 - V1
Path2 = V4 - E5 - V7 - E1 - V1

这些边缘中的每一个都具有权重属性。有了这个,我想得到一个叫做"Big Pi" or "Capital Pi"的序列产品。想想求和(Σ)但用乘法代替加法。

Path1的结果将是E2的权重,或上例中的0.3。虽然Path2的权重为E5.weight * E1.weight,但上例中的0.6 * 0.2 = 0.12将为V3

在这种情况下,我们从顶点V4V1开始,两者都以Path1结束。在这种情况下,我想总结Path2V1的权重,因为两个终点都是V1。这会将0.3 + 0.12 = 0.42的总分作为Path3。如果有V2结尾顶点0.34和得分{[V1, 0.42], [V2,0.34] },则结果列表中必须包含元素; {{1}}。

1 个答案:

答案 0 :(得分:1)

您可以这样做:

gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).as('s').outE.inV.loop('s'){it.loops<3}{true}.path
==>[v[1], e[7][1-knows->2], v[2]]
==>[v[1], e[8][1-knows->4], v[4]]
==>[v[1], e[9][1-created->3], v[3]]
==>[v[1], e[8][1-knows->4], v[4], e[10][4-created->5], v[5]]
==>[v[1], e[8][1-knows->4], v[4], e[11][4-created->3], v[3]]

以上使用玩具图获取一些路径,这些路径使用相同的端点产生多个结果。由于您要为每个路径乘以边缘权重,然后对每个以路径结束的顶点求和,所以看起来所有这些的良好返回值将Map键入端点,其值为列表每条路径的权重列表。为此,我使用了groupBy

gremlin> m=g.v(1).as('s').outE.inV.loop('s'){it.loops<3}{true}.path.groupBy{it[it.size()-1]}{it.findAll{it instanceof Edge}.collect{it.getProperty("weight")}}.cap.next()
==>v[3]=[[0.4], [1.0, 0.4]]
==>v[2]=[[0.5]]
==>v[5]=[[1.0, 1.0]]
==>v[4]=[[1.0]]

groupBy的第一个闭包提供了键(即路径中的最后一个顶点)。第二个闭包过滤Edge个对象并拉出权重以存储在每个键的路径列表中。在此处,您可以使用mMap进行操作以完成计算。在这一点上,我们基本上只是直接做Groovy。以下显示了权重乘积的计算:

gremlin> m.collect{k,v->[(k):v.collect{p->p.inject{product,weight->product*weight}}]}           
==>{v[3]=[0.4, 0.4000000059604645]}
==>{v[2]=[0.5]}
==>{v[5]=[1.0]}
==>{v[4]=[1.0]}

一旦你有这么多,计算每个末端顶点的总和就是用groovy sum函数完成的:

gremlin> m.collect{k,v->[(k):v.collect{p->p.inject{product,weight->product*weight}}.sum()]}
==>{v[3]=0.800000011920929}
==>{v[2]=0.5}
==>{v[5]=1.0}
==>{v[4]=1.0}

请注意,为了便于解释和阅读,我将其分解为多个Gremlin语句,但如果您喜欢单行样式,那么您也可以这样做。将其恢复为单行的最佳方法是向groupBy添加第三个闭包,这将作为计算权重乘积/总和的减少步骤。