我遇到了Gremlin返回重复路径的问题,我想知道是否有人可以帮助我。如果我犯了任何简单的错误,我对Gremlin很陌生。
我的数据库的一个简单形式包括超过50个节点和超过5000个边缘,其中边缘被认为是一个方向,但是在两个节点之间可能存在两个方向的边缘导致循环结构(因此节点A - > B - > ; A),同样你可以(A - > B - > C - > A)。
我想要完成的是遍历网络,返回起始节点和结束节点之间的每条唯一路径,它没有循环。下面是我的代码示例。
final List<List> paths = new ArrayList<List>();
String endNodeID = endNode.getVertex().getId().toString();
new GremlinPipeline<Vertex, ArrayList<Vertex>>(startNode.getVertex())
.as("x").out("OutboundLink").simplePath()
.loop("x", new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
@Override
public Boolean compute(final LoopPipe.LoopBundle<Vertex> loopBundle) {
return loopBundle.getLoops() <= 8;
}
}, new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
@Override
public Boolean compute(final LoopPipe.LoopBundle<Vertex> loopBundle) {
return endNodeID.equals(loopBundle.getObject().getId().toString());
}
}).simplePath().filter(new PipeFunction<Vertex, Boolean>() {
@Override
public Boolean compute(final Vertex arg0) {
return targetId.equals(arg0.getId().toString());
}
}).path(new PipeFunction<Vertex, String>() {
@Override
public String compute(final Vertex vertex) {
return vertex.getId().toString();
}
}).fill(paths);
我相信它的确如此
由此我正在获得以下不良行为 - 重复路径 - 命中endNodeID但已继续的路径。
虽然我之后可以在代码中纠正这个问题(在一次模拟中,它从10000个路径纠正到只有200个),但这似乎是浪费资源。
非常感谢任何协助。
答案 0 :(得分:2)
使用Titan 0.5.4我也没有让simplePath()
为我工作。 API文档表明它的目的是检测和过滤掉循环路径,但可能是对我的误解。我最终得到的是编写自己的循环检测代码。
示例图:
+--+
+------+V1+------+
| +--+ |
v |
^ |
+--+ | v
|V2+-----+
| | +--+
+--+ <----------+V3|
| ++-+
| |
| |
| |
| +--+ |
+----> |V4| <----+
+--+
以下代码生成路径
Gremlin Pipeline:
public static List<List<Element>> findPathsBetweenSimple(final Vertex from, final Vertex to) {
final Object endID = to.getId();
GremlinPipeline<Vertex, List<Element>> pipe = new GremlinPipeline<>(from);
pipe.as("startAt")
.out()
.loop("startAt", new PipeFunction<LoopBundle<Vertex>, Boolean>() {
@SuppressWarnings("unchecked")
@Override
public Boolean compute(LoopBundle<Vertex> lb) {
Boolean doContinue = Boolean.TRUE;
LOG.trace("Loop cnt: " + lb.getLoops() + "; Vertex: " + lb.getObject());
if (containsLoop(lb.getPath(), lb.getObject())) {
LOG.debug("Loop detected in path. Aborting. " + lb.getPath());
doContinue = Boolean.FALSE;
} else if (endID.equals(lb.getObject().getId())) {
LOG.debug("Path found: " + lb.getPath() + ", " + lb.getObject());
doContinue = Boolean.FALSE;
}
return doContinue;
}
})
.has("id", endID)
.path();
return pipe.toList();
}
循环检测:
private static boolean containsLoop(final List<Element> path, Vertex current) {
boolean loopDetected = false;
final List<Vertex> vPath = new ArrayList<>();
for (Element element : path) {
if (element instanceof Vertex) {
vPath.add((Vertex) element);
}
}
vPath.add(current);
for (Vertex v : vPath) {
if (Collections.frequency(vPath, v) > 1) {
loopDetected = true;
break;
}
}
return loopDetected;
}