我创建了一个名为otherV
的用户定义步骤,该步骤从边缘(e
)开始,并采用单个Vertex参数(e.inV
或e.outV
) ,并在该边缘输出其他顶点。
Gremlin.defineStep('otherV', [Edge, Pipe], {Vertex v -> _().bothV.filter{!v.equals(it)}})
我有g=TinkerGraphFactory.createTinkerGraph();
当我像这样传递参数顶点时,otherV
步骤给出了正确的结果:
g.v(1).bothE('knows').otherV(g.v(1)).path{it.name}{it.label}
==>[marko, knows, vadas]
==>[marko, knows, josh]
但是,当我首先在x
步骤中将参数顶点分配给变量(例如,sideEffect
),然后将x
作为参数传递给我的步骤时,它会失败并且错误No such property: x for class: groovysh_evaluate
。
g.v(1).sideEffect{marko=it}.bothE('knows').otherV(marko).path{it.name}{it.label}
No such property: marko for class: groovysh_evaluate
我做错了什么?
以下是otherV
自定义步骤应如何工作的简单说明:
// g is the TinkerGraph
marko = g.v(1); vadas = g.v(2);
edge = g.e(7); // e[7][1-knows->2]
gremlin> edge.otherV(marko).map
==>{name=vadas, age=27}
gremlin> edge.otherV(vadas).map
==>{name=marko, age=29}
答案 0 :(得分:1)
看起来这个问题与闭包中的变量范围有关。我重新构建了你的defineStep,希望能够捕获你的内容:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> Gremlin.defineStep('otherV', [Vertex, Pipe], {l -> _().sideEffect{x=it}.bothE(l).bothV.filter{!x.equals(it)}})
==>null
gremlin> g.v(1).otherV("knows").path{it.name}{it.label}
==>[marko, knows, vadas]
==>[marko, knows, josh]
这似乎是一种更简洁的方式来定义自定义步骤。
这是另一个采用任意边并输出另一个顶点的otherV步骤的方法:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> Gremlin.defineStep('otherV', [Edge, Pipe], {v -> l=[v];_().bothV.except(l).gather.transform{it.size()>1?null:it[0]}})
==>null
gremlin> g.e(11).otherV(g.v(3))
==>v[4]
gremlin> g.e(11).otherV(g.v(4))
==>v[3]
gremlin> g.e(11).otherV(g.v(5))
==>null
有人可能会有更好的方法来做到这一点,但基本上我意识到仅仅评估defineStep中来自两个V的顶点是否与传入的顶点相反是不够的,因为它可能既不匹配头部和尾部。基本上,我使用except()来获取传入的顶点,然后将不匹配的任何内容收集到列表中,然后检查列表以查看大小是否大于1。如果是,则表示传入的顶点既不在边的头部或尾部(我返回null),否则列表中的单个顶点是相反的顶点。