В запросе (кстати, написанном Стивеном Маллеттом в этот вопрос) проблема в том, что он работает в 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
В моем проекте я подключаюсь к серверу gremlin локально с нетронутой конфигурацией по умолчанию, используя Node.js.
Здесь что-то происходит, чего я не понимаю.
1 ответ
Расширяя обход, вы расширили 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()
, они включаются в этот вывод. Поэтому 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 здесь.
Похожие вопросы
Связанные вопросы
Новые вопросы
gremlin
Gremlin - это язык обхода графов и виртуальная машина Apache TinkerPop ™.