Gremlin遍历一棵树,找到每个没有';不包含具有指定属性的节点

Gremlin遍历一棵树,找到每个没有';不包含具有指定属性的节点,gremlin,graph-databases,Gremlin,Graph Databases,我有一棵树,就像一个国家包含州和城市。例如,下图显示的美国包括加利福尼亚州和德克萨斯州,这两个州各有2个城市 一个或多个城市被标记,这意味着它的属性“标记”设置为“真”。在下图中,标记为“旧金山” g.addV().property('name','united states').as('united states'). addV().property('name', 'california').as('california'). addV().property('name', 'los ang

我有一棵树,就像一个国家包含州和城市。例如,下图显示的美国包括加利福尼亚州和德克萨斯州,这两个州各有2个城市

一个或多个城市被标记,这意味着它的属性“标记”设置为“真”。在下图中,标记为“旧金山”

g.addV().property('name','united states').as('united states').
addV().property('name', 'california').as('california').
addV().property('name', 'los angeles').as('los angeles').
addV().property('name', 'san francisco').property('marked', 'true').as('san francisco').
addE('contains').from('united states').to('california').
addE('contains').from('california').to('los angeles').
addE('contains').from('california').to('san francisco').

addV().property('name', 'texas').as('texas').
addV().property('name', 'dallas').as('dallas').
addV().property('name', 'houston').as('houston').
addE('contains').from('united states').to('texas').
addE('contains').from('texas').to('dallas').
addE('contains').from('texas').to('houston')
我想运行一个Gremlin查询,返回所有未标记的城市和州。如果一个州没有标记的城市,它应该返回该州。如果州已标记城市,则不应返回州,但应返回未标记的城市

下面的代码工作正常。它输出德克萨斯州是因为德克萨斯州没有任何城市被标记,返回洛杉矶是因为洛杉矶是加利福尼亚州唯一没有标记的城市

g.V().has('name', 'united states').repeat(out()).until(not(
  repeat(out()).until(has('marked','true'))
)).not(has('marked','true')).values('name')
==>texas
==>los angeles
然而,这是最有效的查询吗?这对我来说似乎效率很低,因为我正在遍历树,但在树的每个节点上,我再次遍历该节点下的树,这似乎很糟糕。有更有效的查询吗?注意:使用3个级别(国家、州和城市)只是一个示例。我的实际用例有3个以上的级别,每个分支可能有不同数量的级别,所以repeat(out())是必要的


谢谢

这并不经常发生,但小精灵似乎不想轻易处理这件事。寻找一个解决方案花了我一段时间,因此,我很不情愿地粘贴Daniel Kuppitz的一些尝试来尝试解决这个问题(尽管事情越深入,算法规则上出现的问题就越多):

也许其中的一些可以让你走上正确的轨道来解决你的问题,或者也许答案仅仅是,没有比你现在拥有的更好的解决方案了

我不确定是否是你的选择,但我想你可以考虑做一个<代码>子图()/<代码>,然后以这样的方式对它进行变异,以便给你提示下一步树会发现什么,然后你可以更有效地查询子图。我想这样做的成本是否值得,取决于这些树木的大小和深度

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV().property('name','united states').as('united states').
......1> addV().property('name', 'california').as('california').
......2> addV().property('name', 'los angeles').as('los angeles').
......3> addV().property('name', 'san francisco').property('marked', 'true').as('san francisco').
......4> addE('contains').from('united states').to('california').
......5> addE('contains').from('california').to('los angeles').
......6> addE('contains').from('california').to('san francisco').
......7> 
......7> addV().property('name', 'texas').as('texas').
......8> addV().property('name', 'dallas').as('dallas').
......9> addV().property('name', 'houston').as('houston').
.....10> addE('contains').from('united states').to('texas').
.....11> addE('contains').from('texas').to('dallas').
.....12> addE('contains').from('texas').to('houston').
.....13> 
.....13> addV().property('name', 'arizona').as('arizona').
.....14> addV().property('name', 'pima').as('pima').
.....15> addV().property('name', 'maricopa').as('maricopa').
.....16> addV().property('name', 'tucson').property('marked', 'true').as('tucson').
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV().property('name','united states').as('united states').
......1> addV().property('name', 'california').as('california').
......2> addV().property('name', 'los angeles').as('los angeles').
......3> addV().property('name', 'san francisco').property('marked', 'true').as('san francisco').
......4> addE('contains').from('united states').to('california').
......5> addE('contains').from('california').to('los angeles').
......6> addE('contains').from('california').to('san francisco').
......7> 
......7> addV().property('name', 'texas').as('texas').
......8> addV().property('name', 'dallas').as('dallas').
......9> addV().property('name', 'houston').as('houston').
.....10> addE('contains').from('united states').to('texas').
.....11> addE('contains').from('texas').to('dallas').
.....12> addE('contains').from('texas').to('houston').
.....13> 
.....13> addV().property('name', 'arizona').as('arizona').
.....14> addV().property('name', 'pima').as('pima').
.....15> addV().property('name', 'maricopa').as('maricopa').
.....16> addV().property('name', 'tucson').property('marked', 'true').as('tucson').
.....17> addV().property('name', 'phoenix').as('phoenix').
.....18> addE('contains').from('united states').to('arizona').
.....19> addE('contains').from('arizona').to('pima').
.....20> addE('contains').from('arizona').to('maricopa').
.....21> addE('contains').from('pima').to('tucson').
.....22> addE('contains').from('maricopa').to('phoenix')
==>e[36][25-contains->30]
gremlin> 
gremlin> solution1 = {
......1>   g.V().has('name', 'united states').
......2>     until(select('result').or().not(outE('contains'))).
......3>       repeat(sack(assign).
......4>              map(out('contains').
......5>                  group().
......6>                    by(coalesce(values('marked'), constant('false')))).
......7>              choose(select('true'),
......8>                       coalesce(select('false'), sack()).project('result'),
......9>                       select('false').unfold())).
.....10>     coalesce(select('result').unfold(),
.....11>              sack()).dedup().
.....12>     values('name')
.....13> }
==>groovysh_evaluate$_run_closure1@3f63a513
gremlin> 
gremlin> solution2 = {
......1>   g.V().has('name', 'united states').
......2>     until(select('result').or().not(outE('contains'))).
......3>       repeat(sack(assign).
......4>              map(out('contains').
......5>                  group().
......6>                    by(coalesce(values('marked'), constant('false')))).
......7>              choose(select('true'),
......8>                       union(select('false').unfold(), sack().project('result')),
......9>                       select('false').unfold())).
.....10>     coalesce(select('result').unfold(),
.....11>              sack()).dedup().
.....12>     values('name')
.....13> }
==>groovysh_evaluate$_run_closure1@53f0d09c
gremlin> 
gremlin> solution1()
==>texas
==>los angeles
==>pima
==>maricopa
gremlin> solution2()
==>texas
==>california
==>pima
==>maricopa
gremlin> 
gremlin> g.V().has('name', 'tucson').properties('marked').drop()
gremlin> g.V().has('name', 'pima').property('marked', 'true').iterate()
gremlin> 
gremlin> 
gremlin> solution1()
==>maricopa
==>texas
==>los angeles
gremlin> solution2()
==>arizona
==>texas
==>california
==>maricopa