Gremlin 查询是否有效取决于上下文

Gremlin query works or not depending on the context

在一个查询中(由 stephen mallette 在 中编写的方式)问题是在 gremlify 中有效,但是当我将它粘贴到我的项目中时给出了错误的输出。

所以我打开了 gremlify 来编写一个数据创建查询,然后将其粘贴到 gremlin 控制台中,这样我就可以在那里测试它,我注意到如果它在 gremlify 的数据创建部分之后执行,它就不起作用查询,据我所知它应该可以工作。

查询是这样的:

g.V().as('a').
  repeat(both().simplePath()).
    times(2).
  where(both().as('a')).
  path().
  map(unfold().limit(3).order().by(id).dedup().fold())
  dedup().
  group('m').
    by(limit(local,2)).
  group('m').
    by(tail(local,2)).
  group('m').
    by(union(limit(local,1),tail(local,1)).fold()).     
  cap('m').
  unfold().
  map(select(values).unfold().unfold().order().by(id).dedup().fold()).
  dedup().
  map(unfold().values('name').fold())

这里有效,输出正确: https://gremlify.com/psiygozr559

这里给出了错误的输出: https://gremlify.com/mqw6ut0y1z (相同的图表,但使用查询创建)

这里它根本没有给出任何输出: https://gremlify.com/fzgmzdq1omq (与之前相同,但第 1 行有所变化)

在我的项目中也给出了不正确的输出,并且我没有像上面的 gremlify 项目那样在查询之前执行任何奇怪的事情。

还有另一个查询做同样的事情,我自己写的,效率较低,但在所有相同的情况下和我的项目中都能完美地工作,请参阅:

https://gremlify.com/zihygx0w8e

https://gremlify.com/xsc6q8dranj

在我的项目中,我使用 Node.js.

在本地连接到 gremlin 服务器,默认配置保持不变

这里发生了一些我不明白的事情。

通过扩展遍历,您已经扩展了 Path。将 addV('j') 放在遍历的前面会添加一些我的原始算法没有考虑到的内容:

gremlin> g.addV("j").sideEffect(V().drop()).sideEffect(
......1>     addV("user").property("name", "luana").as("luana")
......2>     .addV("user").property("name", "luisa").as("luisa")
......3>     .addV("user").property("name", "sabrina").as("sabrina")
......4>     .addV("user").property("name", "marcello").as("marcello")
......5>     .addV("user").property("name", "mario").as("mario")
......6>     .addV("user").property("name", "lidia").as("lidia")
......7>     
......7>     .addE("friend").from("luana").to("luisa")
......8>     .addE("friend").from("luana").to("sabrina")
......9>     .addE("friend").from("luana").to("marcello")
.....10>     .addE("friend").from("luana").to("mario")
.....11>     .addE("friend").from("luana").to("lidia")
.....12>     
.....12>     .addE("friend").from("sabrina").to("luisa")
.....13>     .addE("friend").from("sabrina").to("marcello")
.....14>     .addE("friend").from("sabrina").to("mario")
.....15>     
.....15>     .addE("friend").from("mario").to("luisa")
.....16>     .addE("friend").from("mario").to("marcello")
.....17>     ).V().as('a').
.....18>   repeat(both().simplePath()).
.....19>     times(2).
.....20>   where(both().as('a')).
.....21>   path().by(label)
==>[j,user,user,user]
==>[j,user,user,user]
==>[j,user,user,user]
==>[j,user,user,user]
...
==>[j,user,user,user]

您可以通过命名您关心的路径或以其他方式限制或过滤掉初始路径元素来说明这一点:

gremlin> g.addV("j").sideEffect(V().drop()).sideEffect(
......1>     addV("user").property("name", "luana").as("luana")
......2>     .addV("user").property("name", "luisa").as("luisa")
......3>     .addV("user").property("name", "sabrina").as("sabrina")
......4>     .addV("user").property("name", "marcello").as("marcello")
......5>     .addV("user").property("name", "mario").as("mario")
......6>     .addV("user").property("name", "lidia").as("lidia")
......7>     
......7>     .addE("friend").from("luana").to("luisa")
......8>     .addE("friend").from("luana").to("sabrina")
......9>     .addE("friend").from("luana").to("marcello")
.....10>     .addE("friend").from("luana").to("mario")
.....11>     .addE("friend").from("luana").to("lidia")
.....12>     
.....12>     .addE("friend").from("sabrina").to("luisa")
.....13>     .addE("friend").from("sabrina").to("marcello")
.....14>     .addE("friend").from("sabrina").to("mario")
.....15>     
.....15>     .addE("friend").from("mario").to("luisa")
.....16>     .addE("friend").from("mario").to("marcello")
.....17>     ).V().as('a').
.....18>   repeat(both().simplePath()).
.....19>     times(2).
.....20>   where(both().as('a')).
.....21>   path().from('a').
.....22>   map(unfold().limit(3).order().by(id).dedup().fold()).
.....23>   dedup().
.....24>   group('m').
.....25>     by(limit(local,2)).
.....26>   group('m').
.....27>     by(tail(local,2)).
.....28>   group('m').
.....29>     by(union(limit(local,1),tail(local,1)).fold()).     
.....30>   cap('m').
.....31>   unfold().
.....32>   map(select(values).unfold().unfold().order().by(id).dedup().fold()).
.....33>   dedup().
.....34>   map(unfold().values('name').fold())
==>[luana,luisa,sabrina,mario]
==>[luana,sabrina,marcello,mario]
==>[luana,luisa,sabrina,marcello,mario]

请注意上面的第 21 行,我们只需添加 path().from('a'),即从步骤标签“a”开始路径,然后查询再次开始工作。

关于不使用 sideEffect() 添加示例图形数据的其他示例,请注意 path() 跟随 repeat():

时的输出
gremlin> g.addV("j").sideEffect(V().drop()).
......1>   addV("user").property("name", "luana").as("luana").
......2>   addV("user").property("name", "luisa").as("luisa").
......3>   addV("user").property("name", "sabrina").as("sabrina").
......4>   addV("user").property("name", "marcello").as("marcello").
......5>   addV("user").property("name", "mario").as("mario").
......6>   addV("user").property("name", "lidia").as("lidia").
......7>     
......7>   addE("friend").from("luana").to("luisa").
......8>   addE("friend").from("luana").to("sabrina").
......9>   addE("friend").from("luana").to("marcello").
.....10>   addE("friend").from("luana").to("mario").
.....11>   addE("friend").from("luana").to("lidia").
.....12>     
.....12>   addE("friend").from("sabrina").to("luisa").
.....13>   addE("friend").from("sabrina").to("marcello").
.....14>   addE("friend").from("sabrina").to("mario").
.....15>     
.....15>   addE("friend").from("mario").to("luisa").
.....16>   addE("friend").from("mario").to("marcello").
.....17>   V().as('a').both().path()
==>[v[712],v[713],v[715],v[717],v[719],v[721],v[723],e[725][713-friend->715],e[726][713-friend->717],e[727][713-friend->719],e[728][713-friend->721],e[729][713-friend->723],e[730][717-friend->715],e[731][717-friend->719],e[732][717-friend->721],e[733][721-friend->715],e[734][721-friend->719],v[721],v[715]]
==>[v[712],v[713],v[715],v[717],v[719],v[721],v[723],e[725][713-friend->715],e[726][713-friend->717],e[727][713-friend->719],e[728][713-friend->721],e[729][713-friend->723],e[730][717-friend->715],e[731][717-friend->719],e[732][717-friend->721],e[733][721-friend->715],e[734][721-friend->719],v[721],v[719]]
...
==>[v[712],v[713],v[715],v[717],v[719],v[721],v[723],e[725][713-friend->715],e[726][713-friend->717],e[727][713-friend->719],e[728][713-friend->721],e[729][713-friend->723],e[730][717-friend->715],e[731][717-friend->719],e[732][717-friend->721],e[733][721-friend->715],e[734][721-friend->719],v[719],v[721]]

当您在 sideEffect() 之外添加 vertices/edges 时,它们将包含在该输出中。因此,simplePath() 会在您尝试遍历 V().as('a')!

时立即将它们过滤掉
==>[v[712],v[713],v[715],v[717],v[719],v[721],v[723],e[725][713-friend->715],e[726][713-friend->717],e[727][713-friend->719],e[728][713-friend->721],e[729][713-friend->723],e[730][717-friend->715],e[731][717-friend->719],e[732][717-friend->721],e[733][721-friend->715],e[734][721-friend->719],v[721],v[715]]

看看 v[721] 如何出现两次 - 一次出现在 addV() 上,一次出现在 V() 上。 simplePath() 看到您遍历了那个顶点并返回到它。

我的调试方法(因为答案不是很清楚)是首先 profile() 两次遍历并比较相似部分的计数。我注意到他们开始不同的地方,这让我了解了问题开始的地方。从那里我开始并排执行查询直到我注意到 Path 周围的输出差异。您可以学习一些关于如何分离和调试 Gremlin 查询的知识 here.