【发布时间】:2014-11-04 12:02:00
【问题描述】:
我想检索所有顶点,并为每个顶点计算指向它的“Like”边的数量。
如何在 Gremlin 中编写这种查询?
在 SQL 中,它可能类似于....
SELECT *, (SELECT Count(*) FROM tbl_like l WHERE l.id = b.id) AS LikeCount
FROM tbl_blah b
【问题讨论】:
标签: graph-databases gremlin titan
我想检索所有顶点,并为每个顶点计算指向它的“Like”边的数量。
如何在 Gremlin 中编写这种查询?
在 SQL 中,它可能类似于....
SELECT *, (SELECT Count(*) FROM tbl_like l WHERE l.id = b.id) AS LikeCount
FROM tbl_blah b
【问题讨论】:
标签: graph-databases gremlin titan
例如使用sideEffect 将计数放入地图中(m)
m=[:];g.V.sideEffect{m[it]=it.inE.has('label','like').count()}
省略 0 个喜欢的顶点的替代方案:
m=[:];g.V.inE('like').groupCount(m){it.inV.next()}
编辑
最后是智能解决方案:
m=[:];g.V.groupCount(m){it}{it.a.inE('like').count()}
groupCount 的第一个闭包确定要在映射中更新的键,第二个闭包确定键的值。似乎第二个闭包中的it.a 将当前输入值提供给groupCount(这里是一个顶点)和it.b 输入对象映射中的前一个值。还没有真正找到解释这一点的文档,也许 TinkerPop 的一个家伙可以详细说明 groupCount 闭包的确切用法。
【讨论】:
b 是之前从闭包返回的值。这样,您可以在通过groupCount 的每个项目上增加b。在这种情况下,这不是必需的,因为边数就是你想要的。
我会考虑:
m = g.E.has('label','like').groupBy{it.inV.next()}{1}{it.sum()}.cap.next()
迭代所有边并按标签过滤,在每个“喜欢”边的inV 上分组,并将1 添加到结果的Map。这将带您进入groupBy 的倒数第二个关闭。届时,您将拥有Map 之类的:
[v1:[1,1,1]
v2:[1,1]]
它基本上是一个顶点,1 代表每个“喜欢”的边。回到上面的 Gremlin,对groupBy 的最终关闭是对Map 中的值进行的归约操作。在这种情况下,我们使用 Groovy 的 sum 函数(尽管我认为 size 也可以在这里工作 - 但 sum 似乎更易于阅读)来累加边数。最后,我们使用cap 从管道中提取Map 副作用并将next 提取到一个变量中。
我想这里的缺点是它不会为没有“相似”边的顶点产生结果。如果您需要,那么@Faber 提供的解决方案是更好的选择。您甚至可以从这两种解决方案中挑选一些,最终得到您正在寻找的东西。
【讨论】:
cap了。来自文档:“cap 发出上一步的值(这里是由groupBy 产生的映射),而不是流经它的值(这里是流经groupBy 的边)”!谢谢!但是因此cap 的行为类似于gather,因为它收集了直到cap 步骤的所有对象,对吗?
cap 只是从上一步中提取副作用,而 gather 处理管道本身中的对象,将管道中的所有项目抓取到一个列表中。一个处理管道对象,一个处理副作用....这是一个重要的区别。
不需要副作用...
g.V().transform{[it, it.in('likes').count()]}
【讨论】: