通过扩展遍历,您扩展了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() 之外添加顶点/边时,它们会包含在该输出中。因此,当您尝试遍历V().as('a') 时,simplePath() 会立即将它们过滤掉!
==>[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。