格莱姆林迭代条件遍历

3
我有一个如下结构的图表:
1.一些顶点代表现实世界中的物品和类型,即一个顶点代表“城市”,而特定城市如“伦敦”或“西雅图”则有顶点。每个顶点都可以与其类型顶点有“是一个(is-a)”联系,例如"伦敦" -(is-a)-> "城市""美国" -(is-a)-> "国家"
2.顶点也可以通过“in”关系相互连接,例如"伦敦" -(in)-> "英国""西雅图" -(in)->"华盛顿州"
3.一些顶点可能还具有“in-country”关系,例如"西雅图"->(in-country)->"美国",但有些则没有。
4.可能存在多个链接(例如某些城市可能在两个国家之间有争议,因此会有两个“in-country”或“in”链接)——在这种情况下,应返回多个国家。
任务是针对每个顶点尝试找到其所居住的国家(当然,对于“城市”等通用顶点来说是没有意义的,但在这种情况下它应该只产生null)。所以我尝试做了这样一些事情:
v.as('loopstep').ifThenElse{it.out('is-a').has('ID', 'country').hasNext()}{
 it
}{
 it.ifThenElse{it.out('in-country').hasNext()}{
    it.out('in-country')
 }{
    it.out('in').loop('loopstep'){it.loops < 10 }
 }
}

但是这会在循环中产生NPE,例如:

java.lang.NullPointerException
    at com.tinkerpop.pipes.branch.LoopPipe.getLoops(LoopPipe.java:75)

等等。看起来循环无法看到“loopstep”标签。我做错了吗?编写这样的遍历查询的正确方法是什么?


猜测第二个ifThenElse应该以it开头而不是if。编写一些根据您的描述创建图形的代码会很不错。 - Faber
@Faber 是的,谢谢,已经修正了拼写错误。 - StasM
我不确定我完全理解。首先,您的起始顶点(即v)是一个城市吗?其次,根据您的模式,循环结构的目的是什么?所有城市顶点通过一个或多个标签为“in”或“in-country”的边缘链接到国家 - 那么循环的必要性在哪里?也许我对您的模式有什么误解? - stephen mallette
@stephenmallette 它可以是任何东西——城市、州、国家、城镇、村庄、县等等——可以被定位在另一个对象中的任何对象。循环的重点是递归地跟随“in”关系,直到我们到达一个国家——我们可以通过两种方式到达国家——要么作为以“in”结尾的一系列“in”链,要么作为一系列“in”和“in-country”的链(我们假设“in-country”的目标始终是一个国家)。但是,一个村庄可能没有与一个国家的直接链接——它可能会经过大都市、县、州等。 - StasM
啊 - 从你的问题中没有理解到这一点 - 现在明白了。 - stephen mallette
1个回答

2

我认为你不需要所有的ifThenElse语句。假设我现在正确理解了你的模型,我认为你只需要这个:

gremlin> g = new TinkerGraph()                                                                     
==>tinkergraph[vertices:0 edges:0]
gremlin> g = new TinkerGraph()                                                                     
==>tinkergraph[vertices:0 edges:0]
gremlin> usa = g.addVertex([name:"USA"])
==>v[0]
gremlin> va = g.addVertex([name:"VA"])    
==>v[1]
gremlin> fairfax = g.addVertex([name:"Fairfax"])
==>v[2]
gremlin> country = g.addVertex([ID:"country"])
==>v[3]
gremlin> state = g.addVertex([ID:"state"])
==>v[4]
gremlin> city = g.addVertex([ID:"city"])
==>v[5]
gremlin> g.addEdge(null, fairfax, va, "in")
==>e[6][2-in->1]
gremlin> g.addEdge(null, fairfax, city, "is-a")
==>e[7][2-is-a->5]
gremlin> g.addEdge(null, va, usa, "in")    
==>e[8][1-in->0]
gremlin> g.addEdge(null, va, state, "is-a")
==>e[9][1-is-a->4]
gremlin> g.addEdge(null, fairfax, usa, "in-country")
==>e[10][2-in-country->0]
gremlin> g.addEdge(null, usa, country, "is-a")
==>e[11][0-is-a->3]
gremlin> fairfax.as('x').out('in','in-country').loop('x'){it.loops<10 && it.object.out('is-a').ID.next()!='country'}.dedup.name
==>USA

从最后一行开始解释,使用“in”或“in-country”标签从“city”(即fairfax)遍历。如果我幸运地在“in-country”上遍历,那么我就完成了。然后我循环回到x占位符,只要我循环次数少于10次,并且我所在的当前顶点不是国家-否则我就跳出循环,因为我已经到达了要发出的国家顶点。我进行去重,因为您的模式允许通过“in-country”和“in”获得到达国家的多种方式。根据您的数据集,您可能需要一些错误处理或其他东西,但我认为这应该能激发您想出终极解决方案的灵感。

这看起来不错,只是对于美国它没有返回任何内容。但这是可以修复的,谢谢,它让我走上了正确的道路。 - StasM

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