不使用 Union 的具有可变边缘深度的 Gremlin 查询
Gremlin query with variable edge depth without using Union
我正在尝试组合一个 Gremlin 查询,该查询 returns 对某种边缘类型的 1 到 n 深度产生结果 - 而 不必求助于使用多个用 .union()
.
拼接在一起的查询
我有一些模拟销售办公室结构和在其中工作的人员的测试数据,包括谁管理哪些办公室以及哪些办公室“汇总”在哪些更高级别办公室的管辖下。下面的屏幕截图(实际上来自 Neo4j)显示了我要引用的图表的一个子集。
可以使用以下内容创建图表:
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),那也行。这可能无关紧要,但我将使用 AWS Neptune 作为实际的 Graph 数据库。
在询问有关 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()
编辑哪些类型的顶点 - 如果您不包括该过滤器,您也将 return “办公室”顶点。
我正在尝试组合一个 Gremlin 查询,该查询 returns 对某种边缘类型的 1 到 n 深度产生结果 - 而 不必求助于使用多个用 .union()
.
我有一些模拟销售办公室结构和在其中工作的人员的测试数据,包括谁管理哪些办公室以及哪些办公室“汇总”在哪些更高级别办公室的管辖下。下面的屏幕截图(实际上来自 Neo4j)显示了我要引用的图表的一个子集。
可以使用以下内容创建图表:
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),那也行。这可能无关紧要,但我将使用 AWS Neptune 作为实际的 Graph 数据库。
在询问有关 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()
编辑哪些类型的顶点 - 如果您不包括该过滤器,您也将 return “办公室”顶点。