Gremlin 在 hasId returns 中使用 select 不正确的结果

Gremlin using select in hasId returns incorrect result

我正在尝试执行一个 gremlin 查询,其中稍后在 hasId 子句中重新使用保存的顶点 ID。我看到的是,当我输入文字 Id 时,答案是正确的,但是当我用文字替换 select('deployable_id') 时,答案是不正确的。不幸的是,在我现实生活中的例子中,我无法输入文字 ID。

我想了解为什么会出现这种行为,以及是否有更好的方法来执行此查询来避免此问题。

我正在 运行ning gremlin 对抗 AWS Neptune,但是我也可以仅使用 gremlin 控制台在本地复制这个问题。

在 gremlin 控制台中复制问题的步骤:

设置一个简单的数据集

graph = TinkerGraph.open()
g = traversal().withEmbedded(graph)

g.addV('deployable').property('name', 'd1')
g.addV('deployable').property('name', 'd2')
g.addV('library').property('name', 'l1')
g.addV('class').property('name', 'c1')
g.addV('class').property('name', 'c2')
g.addV('app').property('name', 'a1')
g.addV('app').property('name', 'a2')

g.V().has('name', 'd1').addE('ships').to(V().has('name', 'l1'))
g.V().has('name', 'd2').addE('ships').to(V().has('name', 'l1'))
g.V().has('name', 'l1').addE('includes').to(V().has('name', 'c1'))
g.V().has('name', 'l1').addE('includes').to(V().has('name', 'c2'))
g.V().has('name', 'a1').addE('deploys').to(V().has('name', 'd1'))
g.V().has('name', 'a2').addE('deploys').to(V().has('name', 'd2'))

g.V().has('name', 'a1').addE('loads').to(V().has('name', 'c1'))
g.V().has('name', 'a2').addE('loads').to(V().has('name', 'c2'))

使用此查询查找 d1 的 ID(据我所知它始终为 0)

g.V().has('name', 'd1').id()

运行字面id(即数字0)的查询

g.V().
    has('name', 'd1').
    as('deployable').
    id().as('deployable_id').
    select('deployable').
    out('ships').
    project('library','total_classes', 'loaded_classes').
    by('name').
    by(__.out('includes').count()).
    by(
        __.out('includes').
        where(
            __.in('loads').out('deploys').hasId(0)
        ).count()
    )

这 returns 正确的结果 loaded_classes = 1

==>[library:l1,total_classes:2,loaded_classes:1]

现在 运行 使用 select

的查询
g.V().
    has('name', 'd1').
    as('deployable').
    id().as('deployable_id').
    select('deployable').
    out('ships').
    project('library','total_classes', 'loaded_classes').
    by('name').
    by(__.out('includes').count()).
    by(
        __.out('includes').
        where(
            __.in('loads').out('deploys').hasId(__.select('deployable_id'))
        ).count()
    )

这会产生不正确的结果,其中 loaded_classes = 0

==>[library:l1,total_classes:2,loaded_classes:0]

上面的例子确实有一个解决方案(__.in('loads').out('deploys').has('name', 'd1')),但是这个解决方案在我的实际例子中也不起作用,而且我还无法在一个简单的例子中复制这个问题。

hasId() 没有将 Traversal 作为参数的重载。它接受它是因为签名涉及 ObjectObject 是一个标识符,因此 hasId() 假定您的 Traversal 是要搜索的标识符。图可能应该拒​​绝带有有意义消息的不可接受的标识符,但 TinkerGraph 特别乐于将任何 Object 用作 T.id,因此它允许它。

我可能会 re-write 你的查询使用某种形式 where():

gremlin> g.V().
......1>     has('name', 'd1').
......2>     as('deployable').
......3>     out('ships').
......4>     project('library','total_classes', 'loaded_classes').
......5>     by('name').
......6>     by(__.out('includes').count()).
......7>     by(
......8>         __.out('includes').
......9>         where(
.....10>             __.in('loads').out('deploys').where(eq('deployable'))
.....11>         ).count()
.....12>     )
==>[library:l1,total_classes:2,loaded_classes:1]