Gremlin/Tinkerpop3中如何查询多个顶点及其关系的个数?
How to query for multiple vertices and counts of their relationships in Gremlin/Tinkerpop 3?
我正在使用 Gremlin/Tinkerpop 3 查询存储在 TitanDB 中的图形。
该图包含具有属性的用户顶点,例如 "description",以及表示用户之间关系的边。
我想使用 Gremlin 来获取 1) 按属性的用户和 2) 与其他用户(例如,id = 123)的关系(在这种情况下是任何类型)的数量。为了实现这一点,我在 Gremlin 3 中使用 match
操作,如下所示:
g.V().match('user',__.as('user').has('description',new P(CONTAINS,'developer')),
__.as('user').out().hasId(123).values('name').groupCount('a').cap('a').as('relationships'))
.select()
这个查询工作正常,除非有多个用户顶点返回,例如,因为多个用户在他们的描述中有单词 "developer"。在这种情况下,关系中的计数是所有返回用户与 ID 为 123 的用户之间所有关系的总和,而不是根据需要,每个返回用户的个人计数。
我是不是做错了什么或者这可能是一个错误?
PS:这个问题与我前段时间发布的关于 Tinkerpop 2 中类似查询的问题有关,我在那里遇到了另一个问题:How to select optional graph structures with Gremlin?
这是我使用的示例数据:
graph = TinkerGraph.open()
g = graph.traversal()
v123=graph.addVertex(id,123,"description","developer","name","bob")
v124=graph.addVertex(id,124,"description","developer","name","bill")
v125=graph.addVertex(id,125,"description","developer","name","brandy")
v126=graph.addVertex(id,126,"description","developer","name","beatrice")
v124.addEdge('follows',v125)
v124.addEdge('follows',v123)
v124.addEdge('likes',v126)
v125.addEdge('follows',v123)
v125.addEdge('likes',v123)
v126.addEdge('follows',v123)
v126.addEdge('follows',v124)
我的第一个想法是:"Do we really need match step"?其次,当然,我想用 TP3 的方式写这个,而不是使用 lambda/closure。我在第一次迭代中尝试了各种方法,最接近的是来自 Daniel Kuppitz 的这样的东西:
gremlin> g.V().as('user').local(out().hasId(123).values('name')
.groupCount()).as('relationships').select()
==>[relationships:[:]]
==>[relationships:[bob:1]]
==>[relationships:[bob:2]]
==>[relationships:[bob:1]]
所以这里我们使用了local步来限制local
内的遍历到当前元素。这行得通,但是我们在 select
中丢失了 "user" 标签。为什么? groupCount
是 ReducingBarrierStep
并且路径在这些步骤之后丢失。
好吧,让我们回到match
。我想我可以尝试使用 local
:
进行 match
步遍历
gremlin> g.V().match('user',__.as('user').has('description','developer'),
gremlin> __.as('user').local(out().hasId(123).values('name').groupCount()).as('relationships')).select()
==>[relationships:[:], user:v[123]]
==>[relationships:[bob:1], user:v[124]]
==>[relationships:[bob:2], user:v[125]]
==>[relationships:[bob:1], user:v[126]]
好的 - 成功 - 这就是我们想要的:没有 lambda 和本地计数。但是,它仍然让我感觉:"Do we really need match step"?就在那时,Kuppitz 先生得出了最终答案,该答案大量使用了 by 步骤:
gremlin> g.V().has('description','developer').as("user","relationships").select().by()
.by(out().hasId(123).values("name").groupCount())
==>[user:v[123], relationships:[:]]
==>[user:v[124], relationships:[bob:1]]
==>[user:v[125], relationships:[bob:2]]
==>[user:v[126], relationships:[bob:1]]
如您所见,by
可以链接(在某些步骤上)。第一个 by
按顶点分组,第二个 by
使用 "local" groupCount
处理分组的元素。
我正在使用 Gremlin/Tinkerpop 3 查询存储在 TitanDB 中的图形。
该图包含具有属性的用户顶点,例如 "description",以及表示用户之间关系的边。
我想使用 Gremlin 来获取 1) 按属性的用户和 2) 与其他用户(例如,id = 123)的关系(在这种情况下是任何类型)的数量。为了实现这一点,我在 Gremlin 3 中使用 match
操作,如下所示:
g.V().match('user',__.as('user').has('description',new P(CONTAINS,'developer')),
__.as('user').out().hasId(123).values('name').groupCount('a').cap('a').as('relationships'))
.select()
这个查询工作正常,除非有多个用户顶点返回,例如,因为多个用户在他们的描述中有单词 "developer"。在这种情况下,关系中的计数是所有返回用户与 ID 为 123 的用户之间所有关系的总和,而不是根据需要,每个返回用户的个人计数。
我是不是做错了什么或者这可能是一个错误?
PS:这个问题与我前段时间发布的关于 Tinkerpop 2 中类似查询的问题有关,我在那里遇到了另一个问题:How to select optional graph structures with Gremlin?
这是我使用的示例数据:
graph = TinkerGraph.open()
g = graph.traversal()
v123=graph.addVertex(id,123,"description","developer","name","bob")
v124=graph.addVertex(id,124,"description","developer","name","bill")
v125=graph.addVertex(id,125,"description","developer","name","brandy")
v126=graph.addVertex(id,126,"description","developer","name","beatrice")
v124.addEdge('follows',v125)
v124.addEdge('follows',v123)
v124.addEdge('likes',v126)
v125.addEdge('follows',v123)
v125.addEdge('likes',v123)
v126.addEdge('follows',v123)
v126.addEdge('follows',v124)
我的第一个想法是:"Do we really need match step"?其次,当然,我想用 TP3 的方式写这个,而不是使用 lambda/closure。我在第一次迭代中尝试了各种方法,最接近的是来自 Daniel Kuppitz 的这样的东西:
gremlin> g.V().as('user').local(out().hasId(123).values('name')
.groupCount()).as('relationships').select()
==>[relationships:[:]]
==>[relationships:[bob:1]]
==>[relationships:[bob:2]]
==>[relationships:[bob:1]]
所以这里我们使用了local步来限制local
内的遍历到当前元素。这行得通,但是我们在 select
中丢失了 "user" 标签。为什么? groupCount
是 ReducingBarrierStep
并且路径在这些步骤之后丢失。
好吧,让我们回到match
。我想我可以尝试使用 local
:
match
步遍历
gremlin> g.V().match('user',__.as('user').has('description','developer'),
gremlin> __.as('user').local(out().hasId(123).values('name').groupCount()).as('relationships')).select()
==>[relationships:[:], user:v[123]]
==>[relationships:[bob:1], user:v[124]]
==>[relationships:[bob:2], user:v[125]]
==>[relationships:[bob:1], user:v[126]]
好的 - 成功 - 这就是我们想要的:没有 lambda 和本地计数。但是,它仍然让我感觉:"Do we really need match step"?就在那时,Kuppitz 先生得出了最终答案,该答案大量使用了 by 步骤:
gremlin> g.V().has('description','developer').as("user","relationships").select().by()
.by(out().hasId(123).values("name").groupCount())
==>[user:v[123], relationships:[:]]
==>[user:v[124], relationships:[bob:1]]
==>[user:v[125], relationships:[bob:2]]
==>[user:v[126], relationships:[bob:1]]
如您所见,by
可以链接(在某些步骤上)。第一个 by
按顶点分组,第二个 by
使用 "local" groupCount
处理分组的元素。