反思 CHOOSE 步骤中的 Gremlin 遍历类型 (Edge, Vertex, 属性),可能吗?

Reflect on Gremlin traversal type (Edge, Vertex, Property) in CHOOSE step, possible?

我正在扩展 sparql-to-gremlin 代码以支持完全和部分未绑定的谓词查询,自动化进程可以使用这些查询来探索图形结构。这个想法是你可以连接到一些图形数据库并询问一个具有一定限制的完全未绑定的查询并获取顶点属性、边类型、边属性等。然后可以进一步探索。

我现在可以解决完全未绑定的查询,并且可以解决将主题绑定到顶点的查询。现在,我试图将其组合成一个多文字查询,发现 Gremlin MATCH Step 需要先反映 Traversal 的类型,然后才能决定实际应用哪些步骤。例如,如果遍历产生一个顶点,则要求 out/in 边和属性是有意义的;如果它是 Edge,则要求 out/in 边没有意义,实际上会导致抛出意外类型的错误。

因此问题是,是否可以编写一种反映类型的“switch”语句,然后仅询问在该上下文中有意义的内容?

这是我尝试支持的一种 SPARQL 查询(基于此处描述的众神图 https://old-docs.janusgraph.org/0.1.0/getting-started.html):

https://old-docs.janusgraph.org/0.1.0/images/graph-of-the-gods-2.png

SELECT ?BATTLE ?PRED ?VALUE
WHERE {
    vid:6 ep:battled ?BATTLE .
    ?BATTLE ?PRED ?VALUE .
}

这里我们从一个 id 为 6 的顶点开始,获取带有“battled”标签的传出边引用,然后获取边的所有可能属性及其值。

这里 id 为 6 的顶点是 Hercules,它有 3 个带有标签“battled”的出边到 id 为 9(Nemean)、10(Hydra)和 11(Cerberus)的顶点。我想将 ?PRED 绑定到 v:id(边缘 ID)、v:label(边缘标签)、v:time(边缘时间 属性 值)、v:place(边缘位置 属性 值),eps:battled(sparql-to-gremlin 的扩展,将边缘与 IN 顶点相关联)。

我想我已经解决了你的问题,但我认为我没有一个很好的答案给你。目前,Gremlin 的类型检测不是很好,问题在 TINKERPOP-2234 上仍然悬而未决。对于大多数人来说,当他们在流中有一组混合元素时,典型的解决方法是使用 coalesce()choose() 之类的步骤作为 switch 语句的一种形式,然后找出一些过滤器可以识别对象类型。所以这是我设计的一些混合结果:

gremlin> g.V().union(outE(),__.in())
==>e[9][1-created->3]
==>e[7][1-knows->2]
==>e[8][1-knows->4]
==>v[1]
==>v[1]
==>v[4]
==>v[6]
==>e[10][4-created->5]
==>e[11][4-created->3]
==>v[1]
==>v[4]
==>e[12][6-created->3]

然后我用 hasLabel() 测试我知道只属于顶点的标签,然后其他一切都必须是边:

gremlin> g.V().union(outE(),__.in()).choose(hasLabel('person','software'), values('name'), values('weight'))
==>0.4
==>0.5
==>1.0
==>marko
==>marko
==>josh
==>peter
==>1.0
==>0.4
==>marko
==>josh
==>0.2

显然不理想,但它通常可以解决大多数人的问题。希望我们能看到 TINKERPOP-2234 在 3.5.0 中得到解决。

另一种可能的解决方法是使用 lambda,它在某些用例中效果很好,但我们会尽可能避免使用它们:

gremlin> g.V().union(outE(),__.in()).choose(filter{it.get() instanceof Vertex}, values('name'), values('weight'))
==>0.4
==>0.5
==>1.0
==>marko
==>marko
==>josh
==>peter
==>1.0
==>0.4
==>marko
==>josh
==>0.2