AWS Neptune path () усекает, если используется после цикла repeat ()

g.addV('person').property('firstName','Bob').as('bob').
addV('decision').property('decision','REFER').as('brefer').select('bob').addE('hasDecision').to('brefer').
addV('phone').property('number','123').as('phone').select('bob').addE('hasPhone').to('phone').
addV('person').property('firstName','Jon').as('jon').
addV('decision').property('decision','ACCEPT').as('jaccept').select('jon').addE('hasDecision').to('jaccept').
addV('decision').property('decision','DECLINE').as('jdecline').select('jon').addE('hasDecision').to('jdecline').
addV('email').property('email','[email protected]').as('email').select('jon').addE('hasEmail').to('email').
select('jon').addE('hasPhone').to('phone').
addV('person').property('firstName','Phil').as('phil').
addV('decision').property('decision','DECLINE').as('pdecline').select('phil').addE('hasDecision').to('pdecline').
select('phil').addE('hasEmail').to('email')

На приведенном выше графике Фил связан с Джоном по электронной почте, который, в свою очередь, связан с Бобом по телефону. К каждому узлу человека прикреплены узлы принятия решений. Мне нужно запустить запрос, который вернет путь, если Фил связан с кем-либо в пределах 4 переходов, к которому прикреплен узел решения с решением REFER. Запрос игнорирует узлы решений при его обходе.

Ответ: Фил - ›электронная почта (переход 1) -› Джон (переход 2) - ›телефон (переход 3) -› Боб (переход 4) (поскольку у Боба есть узел решения REFER)

Я пишу это в Gremlin на AWS Neptune. Запрос ниже должен вернуть Боба:

g.V().has('firstName','Phil').repeat(bothE().not(has(label,'hasDecision')).bothV().simplePath())
.until(out().has('decision','REFER')).path().by(valueMap()).by(label())

==>path[{firstName=[Phil]}, hasEmail, {email=[[email protected]]}, hasEmail, {firstName=[Jon]}]

Он нашел Боба - это можно доказать, заменив REFER на X, который ничего не возвращает, - но шаг path () просто завершается у Джона. Кажется, это проблема с шагом repeat (), которую можно показать, упростив запрос, заменив до () на times ()

g.V().has('firstName','Phil').repeat(bothE().not(has(label,'hasDecision')).bothV().simplePath())
.times(2).path().by(valueMap()).by(label())
==>path[{firstName=[Phil]}, hasEmail, {email=[[email protected]]}, hasEmail, {firstName=[Jon]}]

g.V().has('firstName','Phil').repeat(bothE().not(has(label,'hasDecision')).bothV().simplePath())
.times(4).path().by(valueMap()).by(label())
==>path[{firstName=[Phil]}, hasEmail, {email=[[email protected]]}, hasEmail, {firstName=[Jon]}]

Обратите внимание, что последний запрос должен был пройти к Бобу в конце цепочки, но функция path () отказалась от Джона.

Воссоздание запроса без повтора дает правильный путь, но для меня это бесполезно, поскольку целевой узел находится на неизвестном расстоянии.

 g.V().has('firstName','Phil').
bothE().not(has(label,'hasDecision')).bothV().
bothE().not(has(label,'hasDecision')).bothV().
bothE().not(has(label,'hasDecision')).bothV().
bothE().not(has(label,'hasDecision')).bothV().
simplePath().path().by(valueMap()).by(label())
==>path[{firstName=[Phil]}, hasEmail, {email=[[email protected]]}, hasEmail, {firstName=[Jon]}, hasPhone, {number=[123]}, hasPhone, {firstName=[Bob]}]

Кто-нибудь видел это и есть обходной путь? Есть ли альтернатива path ()? Запрос отлично работает на Tinkergraph, BTW (замена has (label (...)) на hasLabel (...))


person Phil Exell    schedule 20.08.2020    source источник
comment
Не уверен, что это актуально для вас, но я использовал запрос repeat.until на Нептуне с переменным расстоянием между узлами. Он отлично работает для меня. gV (). has ('id', args.id) .store ('x') .repeat (inE (). outV (). where (без ('x')). aggregate ('x')). до (has ('id', args.personId)) .limit (1) .path () .by (valueMap (true)) .next ()   -  person codetiger    schedule 20.08.2020


Ответы (1)


Как оказалось, решение здесь простое. Обход должен согласовывать как входящие, так и исходящие ребра. Шаги bothE и bothV разрешают это, но заставляют обход вернуться на себя. Функция dedup () внутри повтора, то есть (bothE () ... bothV (). Dedup (). SimplePath ()) гарантирует, что этого не произойдет.

g.V().has('firstName','Phil').repeat(bothE().not(has(label,'hasDecision')).bothV().dedup().simplePath()).until(out().has('decision','REFER')).path().by(valueMap()).by(label())

Спасибо @codetiger за то, что обратил мое внимание на направление края.

person Phil Exell    schedule 28.08.2020
comment
если вы не хотите, чтобы bothE().bothV() возвращался на себя, тогда вам лучше сделать bothE().otherV(). Таким образом вы проходите только те вершины, из которых не произошли. - person stephen mallette; 02.09.2020