Same query on the same graph returns different results on Neptune vs Gremlify

Viewed 132

I have a large production graph on Neptune which I query using Gremlin Python. I have written a query that should return paths that contain all vertices and edges connected in any way to the queried vertex (root vertex).

It seemed as though this query wasn't always returning all the vertices and edges I expected it to, so I made a small sample graph in Neptune, and the same graph on Gremlify: https://gremlify.com/d4xp81hwd1g

I then ran the query on Neptune and Gremlify twice with a different root vertex for each. In both cases, the paths returned from Neptune were always a subset of the paths returned from Gremlify.

Neptune graph creation:

g.addV("c").property(id, "c139").iterate()
g.addV("c").property(id, "c121").iterate()
g.addV("c").property(id, "c146").iterate()
g.addV("c").property(id, "c128").iterate()

g.addV("d").property(id, "d5E0").iterate()
g.addV("d").property(id, "d546").iterate()
g.addV("d").property(id, "d434").iterate()
g.addV("d").property(id, "dDE5").iterate()
g.addV("d").property(id, "dFFE").iterate()

g.addE("has_d").from_(g.V("c139")).to(g.V("d5E0")).property(id, "c139_d5E0").iterate()
g.addE("has_d").from_(g.V("c139")).to(g.V("d546")).property(id, "c139_d546").iterate()
g.addE("has_d").from_(g.V("c121")).to(g.V("d5E0")).property(id, "c121_d5E0").iterate()
g.addE("has_d").from_(g.V("c121")).to(g.V("d546")).property(id, "c121_d546").iterate()
g.addE("has_d").from_(g.V("c121")).to(g.V("dDE5")).property(id, "c121_dDE5").iterate()
g.addE("has_d").from_(g.V("c121")).to(g.V("dFFE")).property(id, "c121_dFFE").iterate()
g.addE("has_d").from_(g.V("c121")).to(g.V("d434")).property(id, "c121_d434").iterate()
g.addE("has_d").from_(g.V("c146")).to(g.V("dDE5")).property(id, "c146_dDE5").iterate()
g.addE("has_d").from_(g.V("c128")).to(g.V("dFFE")).property(id, "c128_dFFE").iterate()
g.addE("has_d").from_(g.V("c128")).to(g.V("d434")).property(id, "c128_d434").iterate()

Neptune query:

paths = (
    g.V('c121')
    .repeat(bothE().simplePath().otherV())
    .until(not_(bothE().simplePath()))
    .path()
    .by(valueMap(True))
    .toList()
)

for path in paths:
    for element in path:
        print(element[id], end = ' -> ')
    print('')

The Gremlify graph and query can be seen in the link above.

Results:

ROOT VERTEX: c121

Neptune:  c121 -> c121_dDE5 -> dDE5 -> c146_dDE5 -> c146
Gremlify: c121 -> c121_dDE5 -> dDE5 -> c146_dDE5 -> c146

Neptune:  c121 -> c121_d5E0 -> d5E0 -> c139_d5E0 -> c139
Gremlify: c121 -> c121_d5E0 -> d5E0 -> c139_d5E0 -> c139 -> c139_d546 -> d546 -> c121_d546 -> c121

Neptune:  c121 -> c121_dFFE -> dFFE -> c128_dFFE -> c128
Gremlify: c121 -> c121_dFFE -> dFFE -> c128_dFFE -> c128 -> c128_d434 -> d434 -> c121_d434 -> c121

Neptune:  c121 -> c121_d434 -> d434 -> c128_d434 -> c128
Gremlify: c121 -> c121_d434 -> d434 -> c128_d434 -> c128 -> c128_dFFE -> dFFE -> c121_dFFE -> c121

Neptune:  c121 -> c121_d546 -> d546 -> c139_d546 -> c139 ->
Gremlify: c121 -> c121_d546 -> d546 -> c139_d546 -> c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121

ROOT VERTEX: c139

Neptune:  c139 -> c139_d546 -> d546 -> c121_d546 -> c121
Gremlify: c139 -> c139_d546 -> d546 -> c121_d546 -> c121 -> c121_d5E0 -> d5E0 -> c139_d5E0 -> c139

Neptune:  c139 -> c139_d546 -> d546 -> c121_d546 -> c121
Gremlify: c139 -> c139_d546 -> d546 -> c121_d546 -> c121 -> c121_dDE5 -> dDE5 -> c146_dDE5 -> c146

Neptune:  c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121
Gremlify: c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121 -> c121_d546 -> d546 -> c139_d546 -> c139

Neptune:  c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121
Gremlify: c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121 -> c121_dDE5 -> dDE5 -> c146_dDE5 -> c146

Neptune:  c139 -> c139_d546 -> d546 -> c121_d546 -> c121 -> c121_dFFE -> dFFE
Gremlify: c139 -> c139_d546 -> d546 -> c121_d546 -> c121 -> c121_dFFE -> dFFE -> c128_dFFE -> c128 -> c128_d434 -> d434 -> c121_d434 -> c121

Neptune:  c139 -> c139_d546 -> d546 -> c121_d546 -> c121 -> c121_d434 -> d434
Gremlify: c139 -> c139_d546 -> d546 -> c121_d546 -> c121 -> c121_d434 -> d434 -> c128_d434 -> c128 -> c128_dFFE -> dFFE -> c121_dFFE -> c121

Neptune:  c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121 -> c121_dFFE -> dFFE
Gremlify: c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121 -> c121_dFFE -> dFFE -> c128_dFFE -> c128 -> c128_d434 -> d434 -> c121_d434 -> c121

Neptune:  c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121 -> c121_d434 -> d434
Gremlify: c139 -> c139_d5E0 -> d5E0 -> c121_d5E0 -> c121 -> c121_d434 -> d434 -> c128_d434 -> c128 -> c128_dFFE -> dFFE -> c121_dFFE -> c121

Why am I seeing these different results? And how can I achieve the expected results I am getting in Gremlify with my Python queries on Neptune?

1 Answers

Thanks for the details here. Neptune will investigate offline, but as a workaround, please would you try:

g.V("c121")
.repeat(
    union(
        outE().simplePath().inV(),
        inE().simplePath().outV()
    )
)
.until(not(bothE().simplePath()))
.path().by(valueMap(True))
.toList()
Related