首页 > 解决方案 > 如何在没有变量的情况下在 AWS Neptune 中进行复杂的 Gremlin 查询?

问题描述

我正在使用不支持变量的 Amazon Neptune。然而,对于复杂的查询,我需要在多个地方使用一个变量。如何在不为相同数据查询两次的情况下做到这一点?

这是我要解决的问题:

给定一个 start Person,发现PersonsstartPerson通过knows关系最多连接 3 个步骤。返回每个Personnameemail,以及distance(1-3)。

由于 Neptune 不支持变量,我如何在没有变量的情况下在 Gremlin 中编写此查询?

标签: gremlintinkerpoptinkerpop3amazon-neptunegremlinpython

解决方案


我看不出有什么理由需要变量来进行遍历,并且有很多方法可以得到答案。假设这个图:

g = TinkerGraph.open().traversal()
g.addV('person').property('name','A').property('age',20).as('a').
  addV('person').property('name','B').property('age',21).as('b').
  addV('person').property('name','C').property('age',22).as('c').
  addV('person').property('name','D').property('age',19).as('d').
  addV('person').property('name','E').property('age',22).as('e').
  addV('person').property('name','F').property('age',24).as('f').
  addE('next').from('a').to('b').
  addE('next').from('b').to('c').
  addE('next').from('b').to('d').
  addE('next').from('c').to('e').
  addE('next').from('d').to('e').
  addE('next').from('e').to('f').iterate()

您可以执行以下操作:

gremlin> g.V().has('person','name','A').
......1>   repeat(out().
......2>          group('m').
......3>            by(loops()).
......4>            by(valueMap('name','age').by(unfold()).fold())).
......5>     times(3).
......6>   cap('m')
==>[0:[[name:B,age:21]],1:[[name:C,age:22],[name:D,age:19]],2:[[name:E,age:22],[name:E,age:22]]]

通过他们的名字找到一个特定的“人”顶点,在本例中为“A”,然后反复遍历out()并分组您遇到的那些顶点,loops()即您遍历的深度。在这种情况下,我使用valueMap()它来提取您想要的属性。这times(3)是搜索深度的限制。最后你cap()Map我们的group(). 该方法旨在为您提供一些基本结构,以了解如何完成此操作。您也许可以通过这种方式进一步完善它:

gremlin> g.V().has('person','name','A').
......1>   repeat(out().
......2>          group('m').
......3>            by(loops())).
......4>     times(3).
......5>   cap('m').unfold().select(values).unfold().
......6>   dedup().
......7>   valueMap('name','age').by(unfold())
==>[name:B,age:21]
==>[name:C,age:22]
==>[name:D,age:19]
==>[name:E,age:22]

上面的示例从“m”中提取值Map,删除重复项,dedup()然后转换为您想要的结果。也许你一开始就不需要Map(实际上我只是因为这个答案而想到它) - 你可以将store()你的结果简单如下:

gremlin> g.V().has('person','name','A').
......1>   repeat(out().store('m')).
......2>     times(3).
......3>   cap('m').unfold().
......4>   dedup().
......5>   valueMap('name','age').by(unfold())
==>[name:B,age:21]
==>[name:C,age:22]
==>[name:D,age:19]
==>[name:E,age:22]

您可能会考虑使用类似的东西simplePath()来帮助避免一遍又一遍地重新遍历相同的路径。您可以在参考文档中阅读有关该步骤的信息。


推荐阅读