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 客户端的信息,尤其是如果它作为开源可用的话。