Gremlin:按客户端提供的权重对节点进行排序
Gremlin: sorting nodes by weights provided by the client
你好亲爱的小精灵绝地,
我的图表中有一堆具有不同标签的节点:
g.addV("book").property(:genre, "horror").as("b1")
.addV("book").property(:genre, "biography").as("b2")
.addV("book").property(:genre, "sci-fi").as("b3")
.addV("movie").property(:genre, "biography").as("m1")
.addV("movie").property(:genre, "sci-fi").as("m1")
.addV("movie").property(:genre, "horror").as("m3").iterate
我想按类型 属性 对它们进行排序,为来自客户的每个值提供权重,例如:
WEIGHTS = {
"horror": 3,
"biography": 2,
"sci-fi": 1
}
所以这种情况下的结果应该是这样的
[b3, m1, b2, m1, b1, m3]
如果顶点具有权重中未提及的流派,则不应导致错误,此类顶点可能会被简单地忽略或放在结果的末尾。
权重可能会因查询而异,因此我无法将它们存储在图表中。
我的想法是使用 withSideEffect
配置步骤将权重传递给服务器,然后以某种方式使用它对顶点进行排序:
g.withSideEffect("weights", WEIGHTS)
.V().order().by(__.select("weights").select(__.values(:genre)))
.toList()
但显然这是错误的方法,因为它会导致错误:
This traversal parent does not support the replacement of local traversals: org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep
实现我的目标的正确方法是什么?
谢谢!
PS:如果它很重要,我使用我自己的 gremlin 语言变体,用 Ruby 编写,但它的语义或多或少遵循官方 python 客户端的语义。
您可以尝试这种方法,在查询中您可以将值映射到整数,并对这些整数使用简单的顺序。
g.V().as('a').
coalesce(
values("genre").is(eq("horror")).constant(3),
values("genre").is(eq("sci-fi")).constant(1),
values("genre").is(eq("biography")).constant(2),
constant(4)).
order().
select('a')
您实际上与问题的最初尝试非常接近,只是少了一个select
gremlin> g.withSideEffect("weights", ["horror":3,"sci-fi":1,"biography":2]).
......1> V().as('a').
......2> order().
......3> by(select('weights').select(select('a').values('genre'))).
......4> elementMap()
==>[id:42780,label:book,genre:sci-fi]
==>[id:42784,label:movie,genre:sci-fi]
==>[id:42778,label:book,genre:biography]
==>[id:42782,label:movie,genre:biography]
==>[id:42776,label:book,genre:horror]
==>[id:42786,label:movie,genre:horror]
顺便说一句,我很想知道更多关于您的 Ruby 客户端的信息,尤其是如果它作为开源可用的话。
你好亲爱的小精灵绝地,
我的图表中有一堆具有不同标签的节点:
g.addV("book").property(:genre, "horror").as("b1")
.addV("book").property(:genre, "biography").as("b2")
.addV("book").property(:genre, "sci-fi").as("b3")
.addV("movie").property(:genre, "biography").as("m1")
.addV("movie").property(:genre, "sci-fi").as("m1")
.addV("movie").property(:genre, "horror").as("m3").iterate
我想按类型 属性 对它们进行排序,为来自客户的每个值提供权重,例如:
WEIGHTS = {
"horror": 3,
"biography": 2,
"sci-fi": 1
}
所以这种情况下的结果应该是这样的
[b3, m1, b2, m1, b1, m3]
如果顶点具有权重中未提及的流派,则不应导致错误,此类顶点可能会被简单地忽略或放在结果的末尾。
权重可能会因查询而异,因此我无法将它们存储在图表中。
我的想法是使用 withSideEffect
配置步骤将权重传递给服务器,然后以某种方式使用它对顶点进行排序:
g.withSideEffect("weights", WEIGHTS)
.V().order().by(__.select("weights").select(__.values(:genre)))
.toList()
但显然这是错误的方法,因为它会导致错误:
This traversal parent does not support the replacement of local traversals: org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep
实现我的目标的正确方法是什么?
谢谢!
PS:如果它很重要,我使用我自己的 gremlin 语言变体,用 Ruby 编写,但它的语义或多或少遵循官方 python 客户端的语义。
您可以尝试这种方法,在查询中您可以将值映射到整数,并对这些整数使用简单的顺序。
g.V().as('a').
coalesce(
values("genre").is(eq("horror")).constant(3),
values("genre").is(eq("sci-fi")).constant(1),
values("genre").is(eq("biography")).constant(2),
constant(4)).
order().
select('a')
您实际上与问题的最初尝试非常接近,只是少了一个select
gremlin> g.withSideEffect("weights", ["horror":3,"sci-fi":1,"biography":2]).
......1> V().as('a').
......2> order().
......3> by(select('weights').select(select('a').values('genre'))).
......4> elementMap()
==>[id:42780,label:book,genre:sci-fi]
==>[id:42784,label:movie,genre:sci-fi]
==>[id:42778,label:book,genre:biography]
==>[id:42782,label:movie,genre:biography]
==>[id:42776,label:book,genre:horror]
==>[id:42786,label:movie,genre:horror]
顺便说一句,我很想知道更多关于您的 Ruby 客户端的信息,尤其是如果它作为开源可用的话。