微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

不使用Union

如何解决不使用Union

我正在尝试汇总一个Gremlin查询,该查询返回某个边缘类型深度为1到n深度的结果-而无需,必须诉诸使用与.union()缝合在一起的多个查询

我有一些测试数据可以模拟销售办事处和在其中工作的人员的结构,包括谁来管理哪个办事处以及哪个办事处在哪个更高级别的办事处的管辖范围内“汇总”。下面的屏幕快照(实际上是Neo4j的)显示了我要参考的图形的子集。

Graph of sample data

可以使用以下方法创建图形:

g.
addV('Office').as('O_111').property('code','111').
addV('Office').as('O_356').property('code','356').
addV('Office').as('O_279').property('code','279').
addV('Office').as('O_KC5').property('code','KC5').
addE('MERGES_INTO').from('O_356').to('O_111').
addE('MERGES_INTO').from('O_279').to('O_356').
addE('MERGES_INTO').from('O_KC5').to('O_279').
addV('Person').as('Bob').property('name','Bob').
  addE('MANAGES').from('Bob').to('O_111').addE('WORKS_WITH').from('Bob').to('O_111').
addV('Person').as('Michael').property('name','Michael').addE('WORKS_WITH').from('Michael').to('O_111').
addV('Person').as('John').property('name','John').addE('WORKS_WITH').from('John').to('O_111').
addV('Person').as('Rich').property('name','Rich').addE('WORKS_WITH').from('Rich').to('O_111').
addV('Person').as('Matt').property('name','Matt').
  addE('WORKS_WITH').from('Matt').to('O_279').addE('MANAGES').from('Matt').to('O_279').
addV('Person').as('Judy').property('name','Judy').addE('WORKS_WITH').from('Judy').to('O_279').
addV('Person').as('Joe').property('name','Joe'). addE('WORKS_WITH').from('Joe').to('O_279').
addV('Person').as('Ben').property('name','Ben').addE('WORKS_WITH').from('Ben').to('O_279').
addV('Person').as('Ron').property('name','Ron').addE('WORKS_WITH').from('Ron').to('O_KC5').

如果我想查看哪些人(橙色)与Bob直接或间接管理的办公室(粉红色)合作(例如,由于办公室KC5、279和356汇总到Bob的111办公室),我可以使用.union()和类似以下内容以获得正确的结果:

gremlin> g.V().has('Person','name','Bob').
......1>   out('MANAGES').
......2>   union(
......3>     __.in('WORKS_WITH'),......4>     __.in('MERGES_INTO').in('WORKS_WITH'),......5>     __.in('MERGES_INTO').in('MERGES_INTO').in('WORKS_WITH'),......6>     __.in('MERGES_INTO').in('MERGES_INTO').in('MERGES_INTO').in('WORKS_WITH')
......7>     ).
......8>   values('name').fold()
==>[Bob,Michael,John,Rich,Matt,Judy,Joe,Ben,Ron]

这看起来超级冗长而笨拙。那是我唯一的选择吗?有没有比.union()看起来更好的更好方法了?

来自Neo4j世界,我将使用*0..来做深度范围为“ 0或更大”的操作,如下所示:

MATCH (manager:Person {name:'Bob'}) 
OPTIONAL MATCH (manager)-[:MANAGES]->(:Office)<-[:MERGES_INTO*0..]-(:Office)<-[:WORKS_WITH]-(p:Person)
RETURN p

如何在Gremlin中实现相同的目标?即使我不能做开放式交易,但可以做1到某个任意限制(例如1到10),也可以。可能没关系,但是我将对实际的Graph数据库使用AWS Neptune。

解决方法

在询问有关Gremlin的问题时,您的图形图片很漂亮,但是提供一些示例数据的脚本则更好-像这样:

g.addV('person').property('name','michael').as('mi').
  addV('person').property('name','john').as('jo').
  addV('person').property('name','rich').as('ri').
  addV('person').property('name','bob').as('bo').
  addV('person').property('name','matt').as('ma').
  addV('person').property('name','ron').as('ro').
  addV('person').property('name','joe').as('joe').
  addV('person').property('name','ben').as('be').
  addV('person').property('name','judy').as('ju').
  addV('office').property('name','111').as('111').
  addV('office').property('name','356').as('356').
  addV('office').property('name','279').as('279').
  addV('office').property('name','kc5').as('kc5').
  addE('mergesInto').from('kc5').to('279').
  addE('mergesInto').from('279').to('356').
  addE('mergesInto').from('356').to('111').
  addE('worksWith').from('mi').to('111').
  addE('worksWith').from('jo').to('111').
  addE('worksWith').from('ri').to('111').
  addE('worksWith').from('bo').to('111').
  addE('manages').from('bo').to('111').
  addE('worksWith').from('ma').to('279').
  addE('manages').from('ma').to('279').
  addE('worksWith').from('joe').to('279').
  addE('worksWith').from('be').to('279').
  addE('worksWith').from('ju').to('279').
  addE('worksWith').from('ro').to('kc5').iterate()

您的直觉是正确的,其中union()对您想做的事情不太正确。我更喜欢repeat()

gremlin> g.V().has('person','name','bob').
......1>   out('manages').
......2>   repeat(__.in('worksWith','mergesInto')).
......3>     emit(hasLabel('person')).
......4>   values('name')
==>bob
==>michael
==>john
==>rich
==>matt
==>joe
==>ben
==>judy
==>ron

以这种方式遍历任意深度(尽管我们倾向于建议设置某种合理的限制,以免在某些地方遇到意外循环时避免出现问题),并且更为简洁。请注意使用emit()来控制从repeat()返回哪些类型的顶点-如果不包括该过滤器,您还将返回“办公室”顶点。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。