Gremlin: AWS Neptune - получите все листовые узлы для каждого узла в графике в виде CSV

У меня есть простой график с узлами, которые представляют собой повторяющийся идентификатор записи в приведенной ниже форме.

Duplicate Id, Original Id
A,B
B,C
C,D
X,Y
Y,Z

Направленный граф выглядит как A - ›B -› C - ›D, и мне нужен результат CSV, который выглядит как ниже, который имеет каждый узел с конечным листовым узлом без более исходящих ребер.

A,D
B,D
C,D
X,Z
Y,Z

Выше приведен упрощенный сценарий для объяснения проблемы, однако фактические данные будут иметь более сложные сценарии, как показано ниже, где у меня есть 24 узла от A до X, где каждый узел подключен к другим 23, имеющим 24C2 = 276 направленных ребер, и для каждого из 24 узлов I требуется конечный узел, у которого больше нет исходящих ребер.

A,B
A,C
A,D
A,E
A,F
A,G
A,H
A,I
A,J
A,K
A,L
A,M
A,N
A,O
A,P
A,Q
A,R
A,S
A,T
A,U
A,V
A,W
A,X
B,C
B,D
B,E
B,F
B,G
B,H
B,I
B,J
B,K
B,L
B,M
B,N
B,O
B,P
B,Q
B,R
B,S
B,T
B,U
B,V
B,W
B,X
C,D
C,E
C,F
C,G
C,H
C,I
C,J
C,K
C,L
C,M
C,N
C,O
C,P
C,Q
C,R
C,S
C,T
C,U
C,V
C,W
C,X
D,E
D,F
D,G
D,H
D,I
D,J
D,K
D,L
D,M
D,N
D,O
D,P
D,Q
D,R
D,S
D,T
D,U
D,V
D,W
D,X
E,F
E,G
E,H
E,I
E,J
E,K
E,L
E,M
E,N
E,O
E,P
E,Q
E,R
E,S
E,T
E,U
E,V
E,W
E,X
F,G
F,H
F,I
F,J
F,K
F,L
F,M
F,N
F,O
F,P
F,Q
F,R
F,S
F,T
F,U
F,V
F,W
F,X
G,H
G,I
G,J
G,K
G,L
G,M
G,N
G,O
G,P
G,Q
G,R
G,S
G,T
G,U
G,V
G,W
G,X
H,I
H,J
H,K
H,L
H,M
H,N
H,O
H,P
H,Q
H,R
H,S
H,T
H,U
H,V
H,W
H,X
I,J
I,K
I,L
I,M
I,N
I,O
I,P
I,Q
I,R
I,S
I,T
I,U
I,V
I,W
I,X
J,K
J,L
J,M
J,N
J,O
J,P
J,Q
J,R
J,S
J,T
J,U
J,V
J,W
J,X
K,L
K,M
K,N
K,O
K,P
K,Q
K,R
K,S
K,T
K,U
K,V
K,W
K,X
L,M
L,N
L,O
L,P
L,Q
L,R
L,S
L,T
L,U
L,V
L,W
L,X
M,N
M,O
M,P
M,Q
M,R
M,S
M,T
M,U
M,V
M,W
M,X
N,O
N,P
N,Q
N,R
N,S
N,T
N,U
N,V
N,W
N,X
O,P
O,Q
O,R
O,S
O,T
O,U
O,V
O,W
O,X
P,Q
P,R
P,S
P,T
P,U
P,V
P,W
P,X
Q,R
Q,S
Q,T
Q,U
Q,V
Q,W
Q,X
R,S
R,T
R,U
R,V
R,W
R,X
S,T
S,U
S,V
S,W
S,X
T,U
T,V
T,W
T,X
U,V
U,W
U,X
V,W
V,X
W,X

Вот графическая визуализация с использованием Neo4j -  Визуальный график

В приведенном выше случае каждый узел от A до W будет иметь X как конечный узел листа.

Также будут циклические циклы, которых мне нужно избегать в общем решении. Сложить все за один шаг может быть слишком много, но мы будем благодарны за руководство.

Обновление: 2020-10-15. Оптимизация обхода необходима для оптимизации выполнения поиска пути от начального узла к конечному узлу.

Для приведенного ниже сценария данных результат для вершин A и B должен быть

A,G
A,H
B,G
B,H

введите описание изображения здесь

Кратчайший путь от A до G - A- ›C-› E- ›G; возможно ли подавить любые дальнейшие переходы от A к G, когда найден любой 1 кратчайший путь к конечному узлу? иначе это приведет к нежелательному выполнению, особенно для больших кластеров подключенных узлов. Эти шаги необходимо повторить еще раз от A до H, путь которого будет A- ›C-› F- ›H, а затем предотвратить любые дальнейшие попытки найти пути между A и H.

Спасибо


person zulfi123786    schedule 21.09.2020    source источник
comment
Вы внедряете систему хранения с контролем версий, где в вашем примере B - это предыдущая версия A? Можете ли вы перечислить более сложный график, показывающий, что вы подразумеваете под множественными листовыми узлами и циклическими циклами? В общем, циклические циклы не являются идеей для работы с графами, но, возможно, ваша ситуация требует этого. Вы должны стремиться сделать это за один шаг, помимо более простого и производительного кода, это также сохранит гарантии ACIDe от Neptune.   -  person rossb83    schedule 21.09.2020
comment
Еще один уточняющий вопрос. Вы спрашиваете, как написать запрос Gremlin, который будет генерировать второй набор пар, который вы укажете в вопросе? Если это так, было бы полезно, если бы вы могли включить несколько примеров шагов Gremlin addV и addE, которые строят небольшой график, представляющий ваш вариант использования.   -  person Kelvin Lawrence    schedule 22.09.2020
comment
Контекст: идентификаторы - это первичные ключи, которые соответствуют данным профилирования клиентов. Первая запись означает, что запись A является дубликатом (на основе сложных критериев) B (того же клиента), поэтому удалите A и оставьте B. Дубликаты идентифицируются в парах системой, которая берет набор данных и возвращает комбинации повторяющихся записей в наборе данных. . Бизнес-правила определяют, какая из 2 записей в дублированной паре должна быть сохранена, а какая - удалена. Что касается нескольких листовых узлов; Я мог бы иметь такие данные, как A- ›B-› C- ›D & A-› B- ›E, и в этом случае A имеет два листовых узла; D, E (больше никаких исходящих отношений)   -  person zulfi123786    schedule 22.09.2020
comment
Функционально это означает, что нет ясности в отношении того, какая из повторяющихся записей должна быть сохранена, это либо D, либо E. Окончательный набор данных будет использоваться для очистки данных из внешней системы, которая берет идентификатор 2 записи и удаляет одну и сохраняет другой вариант - копирование данных из удаленной записи в сохраненную запись, где в сохраненной записи отсутствуют значения атрибутов. Если система обрабатывает B, C, удаляя B и сохраняя C, а затем находит A, B; он попытается удалить A и обновить B и потерпит неудачу, когда B не существует, поэтому я должен определить конечный узел, в который будет свернут каждый узел.   -  person zulfi123786    schedule 22.09.2020


Ответы (1)


На основе того, что вы предоставили, можно построить следующий график.

g.addV('A').as('a').
  addV('B').as('b').
  addV('C').as('c').
  addV('D').as('d').
  addV('X').as('x').
  addV('Y').as('y').
  addV('Z').as('z').
  addE('dup').from('a').to('b').
  addE('dup').from('b').to('c').
  addE('dup').from('c').to('d').
  addE('dup').from('x').to('y').
  addE('dup').from('y').to('z').
  iterate()  

и следующий запрос, используемый для поиска результатов

gremlin> g.V().
           repeat(out().simplePath()).
           until(__.not(out())).
           path().
             by(label).
           local(
             unfold().
             union(
               limit(1),
               tail()).
             fold())


==>[A,D]
==>[B,D]
==>[C,D]
==>[X,Z]
==>[Y,Z] 

ОБНОВЛЕНО 11 октября 2020 г.

Используя предоставленный вами больший набор данных, я немного изменил запрос, чтобы для каждой начальной вершины находился только один путь к листу. Это работает очень быстро. Без этого, начиная, скажем, с «A», буквально миллионы уникальных путей заканчиваются на «X», поэтому предыдущий запрос становится таким сложным.

gremlin> g.V().
......1>   local(
......2>     repeat(out().simplePath()).
......3>     until(__.not(out())).
......4>     path().
......5>       by(label).
......6>       limit(1)).
......7>   local(
......8>     unfold().
......9>     union(
.....10>       limit(1),
.....11>       tail()).
.....12>     fold())

==>[A,X]
==>[B,X]
==>[C,X]
==>[D,X]
==>[E,X]
==>[F,X]
==>[G,X]
==>[H,X]
==>[I,X]
==>[J,X]
==>[K,X]
==>[L,X]
==>[M,X]
==>[N,X]
==>[O,X]
==>[P,X]
==>[Q,X]
==>[R,X]
==>[S,X]
==>[T,X]
==>[U,X]
==>[V,X]
==>[W,X]

Исключительно для интереса следующий запрос показывает сильно связанный веер вне графика.

gremlin> g.V().group().by(label).by(local(out().label().order().fold())).unfold()

==>A=[B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>B=[C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>C=[D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>D=[E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>E=[F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>F=[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>G=[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>H=[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>I=[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>J=[K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>K=[L, M, N, O, P, Q, R, S, T, U, V, W, X]
==>L=[M, N, O, P, Q, R, S, T, U, V, W, X]
==>M=[N, O, P, Q, R, S, T, U, V, W, X]
==>N=[O, P, Q, R, S, T, U, V, W, X]
==>O=[P, Q, R, S, T, U, V, W, X]
==>P=[Q, R, S, T, U, V, W, X]
==>Q=[R, S, T, U, V, W, X]
==>R=[S, T, U, V, W, X]
==>S=[T, U, V, W, X]
==>T=[U, V, W, X]
==>U=[V, W, X]
==>V=[W, X]
==>W=[X]
==>X=[]

и количество (умножение этих чисел дает большое число), что объясняет, почему поиск всех путей из 'A' является дорогостоящим запросом. Обратите внимание, что шаг simplePath помогает нам убедиться, что мы не следуем никаким циклам. Количество путей от любой вершины до 'X' в этом наборе данных в конечном итоге равно 2 ^ (C-1), где C - это номер в списке ниже для данного начала.

gremlin> g.V().group().by(label).by(local(out().count())).unfold()

==>A=23
==>B=22
==>C=21
==>D=20
==>E=19
==>F=18
==>G=17
==>H=16
==>I=15
==>J=14
==>K=13
==>L=12
==>M=11
==>N=10
==>O=9
==>P=8
==>Q=7
==>R=6
==>S=5
==>T=4
==>U=3
==>V=2
==>W=1
==>X=0
person Kelvin Lawrence    schedule 21.09.2020
comment
Большое спасибо за ваш ответ. У меня около 24 тыс. Вершин и около 26 тыс. Ребер. Мой сервер Neptune с памятью 250 ГБ и 64 ЦП не может выполнить вышеуказанный запрос, и я убедился, что нет циклических циклов, поэтому мне нужно его доработать. Я также попытался ограничиться одним кластером из 24 узлов, связанных друг с другом, с общим количеством ребер 24c2, но запрос продолжает выполняться вечно. gV ('0012K00001heOMhQAM'). repeat (out (). simplePath ()). until (__. not (out ())). path (). by (label) .local (deploy (). union (limit (1 ), хвост ()). сложить ()) - person zulfi123786; 23.09.2020
comment
Что произойдет, если вы замените шаг until чем-то вроде times(3) в качестве простого теста? Если это сработает, попробуйте times(4) и т. Д. Каков глубокий путь оттуда ко всем возможным листовым узлам? - person Kelvin Lawrence; 23.09.2020
comment
Максимальная глубина 24 - person zulfi123786; 23.09.2020
comment
Можете ли вы обновить вопрос с помощью немного большего набора данных? Трудно понять, в чем может быть проблема, не просматривая данные. Если это невозможно, вы можете открыть запрос в службу поддержки или опубликовать сообщение на форуме поддержки Neptune, чтобы инженер службы поддержки мог вам помочь. - person Kelvin Lawrence; 23.09.2020
comment
Спасибо за ответ. Я обновил вопрос с большим набором данных. Когда я запускаю ваш запрос к одному кластеру из 24 узлов, это занимает слишком много времени, поэтому я предполагаю, что мы можем оптимизировать, ограничив 2-й прыжок, чтобы выбрать узел, который не подключен к запускаемому узлу ex- В данных с 24 узлами как в вопросе должны быть указаны Пути для оценки для A; A - ›B / C / D ... X [23 варианта для 1-го перехода] -› X [исключить все узлы, которые напрямую подключены к A]. Повторите то же самое для всех 23 узлов. Надеюсь, это имеет смысл. - person zulfi123786; 06.10.2020
comment
Привет, Кельвин, не могли бы вы взглянуть на обновленный вопрос. Большое спасибо - person zulfi123786; 10.10.2020
comment
Я посмотрю. Благодарим за предоставление дополнительных данных. Возможно, было бы лучше сделать это новым вопросом, поскольку исходный ответ решил исходный вопрос, и это довольно большой шаг вперед по сравнению с этим вопросом. Я напишу сценарий, чтобы превратить ваши данные в график, и посмотрю. - person Kelvin Lawrence; 11.10.2020
comment
Я обновил ответ на основе того, что я наблюдал, используя ваш больший набор данных. - person Kelvin Lawrence; 11.10.2020
comment
Результат выглядел потрясающе, всего 1 последняя проблема, которая все еще существует, запрос ограничивается первым найденным листовым узлом, начиная с любой вершины, которая не обрабатывает случай, если на входе было еще 2 узла [X, Y] и [X, Z ]. В этом случае запрос, начинающийся с вершины A, приведет к [A, Y] или [A, Z], но не к обоим сразу, и я не могу заранее определить максимальное количество конечных узлов. Я предполагаю, нужен ли интеллект инопланетного уровня для настройки, чтобы справиться с этим случаем, особенно для карты такого размера, как в этом примере. Извините, что добавляю сложности, но у меня нет выбора, поскольку данные реального мира могут отображаться во всех формах и формах. - person zulfi123786; 14.10.2020
comment
Для новичка ваша книга «Практический гремлин» очень помогла мне сделать первые шаги. @Kelvin Lawrence - Если вы считаете, что мой случай требует, чтобы я изучил определенные разделы этой книги - пожалуйста, направьте меня к соответствующим разделам. - person zulfi123786; 19.10.2020
comment
На данный момент вопрос немного изменился по сравнению с оригиналом, на который я дал пару ответов. Возможно, было бы лучше создать новый вопрос и включить новый набор данных выборки, состоящий из addV и addE шагов, которые создают график для анализа с учетом этих дополнительных требований. - person Kelvin Lawrence; 22.10.2020