我想获取图中所有连接的子图,它们由两个关系Rel1和Rel2连接。我有一个起始节点类型(不是确切的节点)。
目前我有以下基本查询,它给出了从n1到n2的所有路径,从2到10跳。
CYPHER 2.3 MATCH p = (n1:H)-[r:Rel1|Rel2*2..10]-(n2:H) WITH nodes(p) as result return result
但我需要连接这些路径的连接子图。任何建议或起点都会有所帮助。
我试过的其他事情是TraversalDescription java API进行深度优先搜索,但是它不采用起始节点类型而是采用特定的起始节点?
答案 0 :(得分:1)
[增订]
expanding subgraphs有几个APOC程序。
apoc.path.subgraphNodes
似乎与您的用例最直接相关。有一些使用here的例子。
这是一个稍微简化的示例,它也使用apoc.periodic.commit
(重复执行Cypher查询,直到它返回0或NULL
)和apoc.coll.subtract
(从一个集合中减去另一个集合)。在此示例中,创建Temp
节点以保留临时数据,并在最后删除它。返回的result
应该是对象的集合。每个对象都有一个subgraph_ids
集合,其中包含属于同一子图的节点的本机ID。
MATCH (n:H)-[:Rel1|Rel2]-(:X)-[:Rel1|Rel2]-(:H)
WITH COLLECT(DISTINCT ID(n)) AS ids
CREATE (x:Temp {ids: ids, result: []})
WITH x
CALL apoc.periodic.commit(
"MATCH (x:Temp) " +
"CALL apoc.path.subgraphNodes(x.ids[0], {relationshipFilter:'Rel1|Rel2', labelFilter:'H|X', filterStartNode:false, limit:-1}) YIELD node " +
"WITH x, COLLECT(ID(node)) AS subgraph_ids " +
"SET x.ids = apoc.coll.subtract(x.ids, subgraph_ids) " +
"SET x.result = x.result + {subgraph_ids: subgraph_ids} " +
"RETURN SIZE(x.ids);"
,
NULL) YIELD updates
WITH x, x.result AS result
DELETE x
RETURN result;
顶部的MATCH
子句查找属于具有至少2个H
和/或Rel1
关系的子图的Rel2
个节点。这些节点的本机ID用于初始化ids
节点的Temp
集合。
由apoc.periodic.commit
执行的Cypher代码将重复执行:
ids
Rel|Rel2
类型和X|H
标签),其中包含具有该ID的节点ids
result
节点的Temp
集合ids
集合的当前大小(如果为0,则apoc.periodic.commit
将完成执行。)您可以修改此查询以返回实际节点,过滤具有特定标签的节点,等等。
答案 1 :(得分:0)
[增订]
一般情况下,我建议您考虑为Evaluator
编写自定义TraversalDescription
课程。在那里,您可以根据节点或关系类型轻松包含/排除/修剪等。将Evaluator视为一组规则,您的遍历将针对它找到的每个Path重复引用这些规则。这是一个基本的例子。
评估员:
public class MyEvaluator implements Evaluator {
Label someLabel;
@Override
public execute(Path path) {
if (path.length() == 0) {
return Evaluation.EXCLUDE_AND_CONTINUE;
}
if (path.lastRelationship().getEndNode().hasLabel(someLabel)) {
return Evaluation.INCLUDE_AND_CONTINUE;
}
return Evaluation.EXCLUDE_AND_PRUNE;
}
}
然后将其插入TraversalDescription:
public Stream<Path> myTraversal(Node startNode) {
GraphDatabaseService db;
TraversalDescription td = db.getTraversalDescription().evaluator(new MyEvaluator()).depthFirst();
Traverser tv = td.traverse(someStartNode);
return tv.stream();
}
您是将它放在存储过程还是嵌入式实例中?