Gremlin:AWS Neptune-获取图中每个节点的所有叶节点为CSV

问题描述

我有一个简单的图,其中的节点表示以下形式的重复记录ID

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

有向图看起来像A-> B-> C-> D,我想要下面的CSV结果,该结果具有每个具有最终叶节点且没有更多输出边缘的节点

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

上面是一个简单的场景,用于解释该问题,但是实际数据将具有更复杂的场景,如下所示,其中我有24个从A到X的节点,每个节点都连接到其他23个具有24C2 = 276有向边的节点,并且对于每个24个节点,我需要没有更多输出边缘的最终节点。

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,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,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的图形可视化-

Visual Graph

对于上述情况,每个节点A到W都将X作为最终叶节点。

在整体解决方案中,还需要避免循环循环。一步一步完成所有内容可能会太多,但是希望您能得到指导。

更新时间:2020-10-15 遍历优化需要优化执行过程,以查找从起始节点到叶节点的路径

对于以下数据场景,顶点A和B的结果应为

A,H

enter image description here

从A到G的最短路径是A-> C-> E-> G;找到任何一条通往叶节点的最短路径时,是否有可能抑制从A到G的任何进一步遍历?否则会导致不必要的执行,尤其是对于连接的节点的较大群集。需要再次从A到H重复此步骤,其路径将为A-> C-> F-> H,然后阻止进一步尝试查找A和H之间的路径。

谢谢

解决方法

根据您提供的内容,可以构建以下图形。

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] 

已于2020年10月11日更新

使用您提供的较大数据集,我对查询进行了一些调整,以便对于每个起始顶点,仅找到到叶的一条路径。运行非常迅速。如果不这样做,从“ 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,X]
==>C=[D,X]
==>D=[E,X]
==>E=[F,X]
==>F=[G,X]
==>G=[H,X]
==>H=[I,X]
==>I=[J,X]
==>J=[K,X]
==>K=[L,X]
==>L=[M,X]
==>M=[N,X]
==>N=[O,X]
==>O=[P,X]
==>P=[Q,X]
==>Q=[R,X]
==>R=[S,X]
==>S=[T,X]
==>T=[U,X]
==>U=[V,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