格莱姆林合并以添加多个顶点和边

7

现在,我可以生成一个查询来创建任意数量的顶点和边。

例如:

g.V().
addV('vert1').as('a').
addV('vert2').as('b').
addE('has').from('a').to('b')

^^^^^^^^^^^^^ 这个很好用,是吧?现在让我们创建一个只有在标签唯一的情况下才会创建这些顶点的Gremlin查询。然后在两者之间创建一条边。

g.V().has(label,'vert1').fold().
    coalesce(
        unfold(),
        addV('vert1')
    ).as('a').
    V().has(label,'vert2').fold().
    coalesce(
        unfold(),
        addV('vert2')
    ).as('b').
    addE('has').from('a').to('b')

^^^^^^^^^^^^^这个不起作用

希望你能理解我想做什么。有谁能帮帮我吗?

谢谢


在AWS Neptune中,第一行g.V().addV('vert1').as('a').addV('vert2').as('b').addE('has').from('a').to('b')对我无效。有任何想法为什么?似乎.as()是无效的语法。 - cryanbhu
你看到了什么错误? - Austin Malpede
去掉开头的“.V()”。它看起来像g.addV('vert1').as('a').addV('vert2').as('b').addE('has').from('a').to('b')。 - Austin Malpede
1
查看此处的源代码 https://github.com/apache/tinkerpop/blob/master/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py,我无法看到定义 as 步骤。这非常奇怪,不确定为什么会这样。这可能是向 @stephenmalette 提出的问题。您是否可以使用其他替代语言?我知道 gremlin.net 非常发达。 - Austin Malpede
1
经过进一步调查Python遍历类,看起来步骤被定义为as_。尝试g.addV('vert1').as_('a').addV('vert2').as_('b').addE('has').from('a').to('b')。祝编码愉快! - Austin Malpede
显示剩余3条评论
2个回答

11

你的查询中有一个fold(),它是在as('a')步骤标签之后的ReducingBarrierStep。在该步骤之后,“a”路径历史记录将丢失。您可以在此处阅读更多有关Gremlin的说明

您只需要重新编写查询以解决该问题 - 一种方法可能是聚合“a”的值而不仅仅是命名步骤“a”:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.V().
......1>   has(label,'vert1').fold().
......2>   coalesce(unfold(),
......3>            addV('vert1')).aggregate('a').
......4>   V().has(label,'vert2').fold().
......5>   coalesce(unfold(),
......6>            addV('vert2')).as('b').
......7>   select('a').unfold().
......8>   addE('has').to('b')
==>e[2][0-has->1]

如果您需要返回所有元素,只需对返回的边缘进行project(),并根据需要转换结果:

gremlin> g.V().
......1>   has(label,'vert1').fold().
......2>   coalesce(unfold(),
......3>            addV('vert1')).aggregate('a').
......4>   V().has(label,'vert2').fold().
......5>   coalesce(unfold(),
......6>            addV('vert2')).as('b').
......7>   select('a').unfold().
......8>   addE('has').to('b').
......9>   project('e','in','out').
.....10>     by().
.....11>     by(inV()).
.....12>     by(outV())
==>[e:e[2][0-has->1],in:v[1],out:v[0]]

当然,最后使用select()可能也不是那么糟糕:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.V().
......1>   has(label,'vert1').fold().
......2>   coalesce(unfold(),
......3>            addV('vert1')).aggregate('a').
......4>   V().has(label,'vert2').fold().
......5>   coalesce(unfold(),
......6>            addV('vert2')).as('b').
......7>   select('a').unfold().
......8>   addE('has').to('b').as('x').
......9>   select('a','b','x')
==>[a:[v[0]],b:v[1],x:e[2][0-has->1]]

是否可以将'a'展开存储,以便可以像addE('has').from('a').to('b')这样构建边缘? - Austin Malpede
1
回答我的评论,看起来addE('has').from(select('a').unfold()).to(select('b').unfold)就是我要找的。感谢你的帮助Stephan。你是图形之王。 - Austin Malpede
你提出的解决方案中,是否有办法将所有创建的内容都返回?你可以看到 e[2][0-has->1] 是你的返回值。如果我想要返回两个顶点怎么办?希望有一种替代方法,而不是在结尾添加 select('a','b')。 - Austin Malpede
更新了我的答案 - 我只需对结果边进行 project()。我认为你的 select() 想法也不错。实际上,这可能是最有效的方法,因为这些元素已经在内存中了。 - stephen mallette
嗨@stephenmallette,你能帮我回答这里的问题吗?https://stackoverflow.com/questions/54265985/create-if-not-exist-vertex-and-edge-in-1-query-gremlin - thangdc94

0

我也在寻找一种幂等的方式来创建多个顶点并获得结果。 (我使用Cosmos DB的Gremlin API,而使用fold...coalesce...unfold的典型解决方案在链接在一起时不起作用。)

通过一些实验,我想出了这个替代方案,其复杂度随着添加更多顶点而线性增加。 我正在使用inject()来人为地创建第一次调用coalesce()的“源”。

g.inject("0")
  .coalesce(__.V(['pk1','00']), addV('MyV')
    .property('id','00')
    .property('partitionKey','pk1')).as('x')
  .coalesce(__.V(['pk1','01']), addV('MyV')
    .property('id','01')
    .property('partitionKey','pk1'))
    .as('x')
  .coalesce(__.V(['pk1','02']), addV('MyV')
    .property('id','02')
    .property('partitionKey','pk1'))
    .as('x')
.select('x')

对于那些不关心分区键的人,代码看起来是这样的:

g.inject("0")
  .coalesce(__.V('00'), addV('MyV').property('id','00')).as('x')
  .coalesce(__.V('01'), addV('MyV').property('id','01')).as('x')
  .coalesce(__.V('02'), addV('MyV').property('id','02')).as('x')
.select('x')

此外,我们可以通过提供唯一标签(使用as())在同一时间创建新顶点之间的任意数量的边。
g.inject("0")
  .coalesce(__.V(['pk2','05']), addV('MyV').property('id','05')
    .property('partitionKey','pk2')
    .property('ABC','123467890'))
    .as('x').as('a')
  .coalesce(__.V(['pk2','06']), addV('MyV').property('id','06')
    .property('partitionKey','pk2')
    .property('ABC','123467890'))
    .as('x')
  .coalesce(g.E(['pk2','07']), addE('MyE').property('id','07').from('a'))
    .as('x')
.select('x')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接