【问题标题】:Gremlin Big Pi operation (product of a sequence of terms) followed by id-based summationGremlin Big Pi 运算(一系列术语的乘积),然后是基于 id 的求和
【发布时间】:2013-12-08 15:09:24
【问题描述】:

我有一个如下所示的数据集:

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_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])

希望这有点可以理解。

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

我已经四处寻找答案,但还没有找到解决方法。


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

查询时,我正在寻找子字符串等于“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

在这种情况下,我们从顶点V3V4 开始,并且都以V1 结束。在这种情况下,我想将Path1Path2 的权重相加,因为两个端点都是V1。这将使V1 的总得分为0.3 + 0.12 = 0.42。如果有一个Path3,其顶点为V2,得分为0.34,那么结果列表将包含其中的元素; {[V1, 0.42], [V2,0.34] }.

【问题讨论】:

    标签: graph-databases gremlin tinkerpop


    【解决方案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 添加第三个闭包,这将作为计算权重乘积/总和的减少步骤。

    【讨论】:

    • 非常感谢!真的帮了我! :D 这里发生了很多事情。对我来说,这类似于紧凑性的正则表达式。真的很好,也很难
    • @Cort3z 我对代码进行了微调,以正确键入Map 的最终表示。当它应该是“最后一个顶点”本身时,它最初显示为“k”。
    • 我自己想通了。我最终制作了元组[k, v.collect... ,但是当我使用你的方法时,我得到了一个奇怪的结果。我得到这样的信息:==&gt; {"86384"=&gt;{"_value"=&gt;0.6137, "_key"=&gt;{"some_data_property_on_vertex"=&gt;"some data", "_id"=&gt;86384, "_type"=&gt;"vertex"}}}。这可能是由于我的 rex 包装器。无论如何,我需要对其进行排序,因此将其作为元组进行 [Vertex, result] 可以让我轻松排序。
    猜你喜欢
    • 2017-04-07
    • 1970-01-01
    • 2019-09-20
    • 2016-05-21
    • 2017-06-18
    • 2016-09-26
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    相关资源
    最近更新 更多