图从单个顶点遍历到 N 个顶点
Graph Traversing From Single Vertex to N Vertices
我有以下示例图:
我得到根节点 LV
和 Map<Vertex, Vertex>
其中包含:
Map = {<A_T, A_V>, <B_T, B_V>, <C_T, C_V>, ... <N_T, N_V>}
我正在尝试创建一个从 LV
开始并到达每个叶子 A_T, A_V, B_T, B_V, C_T, C_V
的遍历。最初我想这样构建我的遍历:
GraphTraversal traversal = graph().traversal().V(LV.id());
traversal.and(out().hasId(A_T.id(), A_V.id()),
out().hasId(B_T.id(), B_V.id()),
out().hasId(C_T.id(), C_V.id()),
...
out().hasId(N_T.id(), N_V.id()));
问题是 .and(Object . . .)
不能动态添加(据我所知)并且 N
可以是任何数字所以有一次我想要:
traversal.and(out().hasId(A_T.id(), A_V.id()),
out().hasId(B_T.id(), B_V.id());
在另一个我想要的:
traversal.and(out().hasId(A_T.id(), A_V.id()),
out().hasId(B_T.id(), B_V.id()),
out().hasId(C_T.id(), C_V.id()),
out().hasId(D_T.id(), D_V.id()));
此遍历应该用作 LV
和 Map
中所有组件之间的现有结构的验证。
有什么方法可以实现这个功能吗?
解决了。一如既往,我将 post 我的解决方案适用于可能遇到类似问题的任何人。
问题是 and(...)
方法可以采用多个参数。所以我可以动态地构建最终的遍历。具体我可以做到以下几点。
public void awesomeTraversal(Vertex LV, Map<Vertex, Vertex> vertexMap){
GraphTraversal<Vertex, Vertex> traversal = graph.traversal().V(LV.id()); //Start at LV
ArrayList<GraphTraversal> innerTraversals = new ArrayList<>();
for(Map.Entry<Vertex, Vertex> v : vertexMap){
// Check you can go to X_T
innerTraversals.add(__.out().out().is(entry.getKey()));
//Check you can go to X_V
innerTraversals.add(__.out().out().is(entry.getValue()));
}
//Filter via and.
traversal = traversal.and(innerTraversal.toArray(GraphTraversal[innerTraversals.size()]));
if(traversal.hasNext()){
System.out.println("Found structure");
} else {
System.out.println("No structure");
}
}
这似乎对我有用。欢迎任何改进。
让我们先创建您的示例图表和地图:
graph = TinkerGraph.open()
names = ["LV",
"A_C","A_T","A_V",
"B_C","B_T","B_V",
"C_C","C_T","C_V"]
vertices = names.collectEntries { def name ->
[name, graph.addVertex("name", name)]
}
vertices["LV"].addEdge("link", vertices["A_C"])
vertices["LV"].addEdge("link", vertices["B_C"])
vertices["LV"].addEdge("link", vertices["C_C"])
vertices["A_C"].addEdge("link", vertices["A_T"])
vertices["A_C"].addEdge("link", vertices["A_V"])
vertices["B_C"].addEdge("link", vertices["B_T"])
vertices["B_C"].addEdge("link", vertices["B_V"])
vertices["C_C"].addEdge("link", vertices["C_T"])
vertices["C_C"].addEdge("link", vertices["C_V"])
m = [:]
m.put(vertices["A_T"], vertices["A_V"])
m.put(vertices["B_T"], vertices["B_V"])
m.put(vertices["C_T"], vertices["C_V"])
现在,要判断是否可以找到结构,您可以这样做:
leafs = m.keySet() + m.values()
g = graph.traversal()
found = g.V(vertices["LV"]).out().out().fold().
where(count(local).is(m.size() << 1)).
not(unfold().is(without(leafs))).hasNext()
这是 Gremlin 控制台中的结果:
gremlin> found = g.V(vertices["LV"]).out().out().fold().
gremlin> where(count(local).is(m.size() << 1)).
gremlin> not(unfold().is(without(leafs))).hasNext()
==>true
如果我们向地图添加一些不属于结构的项目:
gremlin> found = g.V(vertices["LV"]).out().out().fold().
gremlin> where(count(local).is(m.size() << 1)).
gremlin> not(unfold().is(without(leafs))).hasNext()
==>false
我有以下示例图:
我得到根节点 LV
和 Map<Vertex, Vertex>
其中包含:
Map = {<A_T, A_V>, <B_T, B_V>, <C_T, C_V>, ... <N_T, N_V>}
我正在尝试创建一个从 LV
开始并到达每个叶子 A_T, A_V, B_T, B_V, C_T, C_V
的遍历。最初我想这样构建我的遍历:
GraphTraversal traversal = graph().traversal().V(LV.id());
traversal.and(out().hasId(A_T.id(), A_V.id()),
out().hasId(B_T.id(), B_V.id()),
out().hasId(C_T.id(), C_V.id()),
...
out().hasId(N_T.id(), N_V.id()));
问题是 .and(Object . . .)
不能动态添加(据我所知)并且 N
可以是任何数字所以有一次我想要:
traversal.and(out().hasId(A_T.id(), A_V.id()),
out().hasId(B_T.id(), B_V.id());
在另一个我想要的:
traversal.and(out().hasId(A_T.id(), A_V.id()),
out().hasId(B_T.id(), B_V.id()),
out().hasId(C_T.id(), C_V.id()),
out().hasId(D_T.id(), D_V.id()));
此遍历应该用作 LV
和 Map
中所有组件之间的现有结构的验证。
有什么方法可以实现这个功能吗?
解决了。一如既往,我将 post 我的解决方案适用于可能遇到类似问题的任何人。
问题是 and(...)
方法可以采用多个参数。所以我可以动态地构建最终的遍历。具体我可以做到以下几点。
public void awesomeTraversal(Vertex LV, Map<Vertex, Vertex> vertexMap){
GraphTraversal<Vertex, Vertex> traversal = graph.traversal().V(LV.id()); //Start at LV
ArrayList<GraphTraversal> innerTraversals = new ArrayList<>();
for(Map.Entry<Vertex, Vertex> v : vertexMap){
// Check you can go to X_T
innerTraversals.add(__.out().out().is(entry.getKey()));
//Check you can go to X_V
innerTraversals.add(__.out().out().is(entry.getValue()));
}
//Filter via and.
traversal = traversal.and(innerTraversal.toArray(GraphTraversal[innerTraversals.size()]));
if(traversal.hasNext()){
System.out.println("Found structure");
} else {
System.out.println("No structure");
}
}
这似乎对我有用。欢迎任何改进。
让我们先创建您的示例图表和地图:
graph = TinkerGraph.open()
names = ["LV",
"A_C","A_T","A_V",
"B_C","B_T","B_V",
"C_C","C_T","C_V"]
vertices = names.collectEntries { def name ->
[name, graph.addVertex("name", name)]
}
vertices["LV"].addEdge("link", vertices["A_C"])
vertices["LV"].addEdge("link", vertices["B_C"])
vertices["LV"].addEdge("link", vertices["C_C"])
vertices["A_C"].addEdge("link", vertices["A_T"])
vertices["A_C"].addEdge("link", vertices["A_V"])
vertices["B_C"].addEdge("link", vertices["B_T"])
vertices["B_C"].addEdge("link", vertices["B_V"])
vertices["C_C"].addEdge("link", vertices["C_T"])
vertices["C_C"].addEdge("link", vertices["C_V"])
m = [:]
m.put(vertices["A_T"], vertices["A_V"])
m.put(vertices["B_T"], vertices["B_V"])
m.put(vertices["C_T"], vertices["C_V"])
现在,要判断是否可以找到结构,您可以这样做:
leafs = m.keySet() + m.values()
g = graph.traversal()
found = g.V(vertices["LV"]).out().out().fold().
where(count(local).is(m.size() << 1)).
not(unfold().is(without(leafs))).hasNext()
这是 Gremlin 控制台中的结果:
gremlin> found = g.V(vertices["LV"]).out().out().fold().
gremlin> where(count(local).is(m.size() << 1)).
gremlin> not(unfold().is(without(leafs))).hasNext()
==>true
如果我们向地图添加一些不属于结构的项目:
gremlin> found = g.V(vertices["LV"]).out().out().fold().
gremlin> where(count(local).is(m.size() << 1)).
gremlin> not(unfold().is(without(leafs))).hasNext()
==>false