我有一个包含多个小子图的图表。目标是当且仅当子图中的所有节点都是蓝色时,将子图的所有蓝色节点标记为RED。如果子图中的一个节点具有不同的颜色GREEN,那么我们将不会更改该子图中节点的颜色。
这是我正在使用的查询:
MATCH (a:BLUE) WHERE NOT (a)-[*]-(:GREEN) WITH a LIMIT 10000 SET a:RED REMOVE a:BLUE
问题是它很慢,因为它需要多次遍历同一个子图。例如:
要将A标记为红色,需要遍历A-B-C。然后,再次标记B,它需要遍历A-B-C。同样,标记C.
我想知道是否有任何方法可以一次性标记子图中的所有节点,而不是一次又一次地访问同一个子图。如果可以,那么它会减少查询时间受很多因素影响。
答案 0 :(得分:1)
我还没有使用图算法插件,但这通常可以比使用APOC Procedures的纯Cypher更快地完成,尽管所有相关子图中的所有节点都需要处理以提取到a连接子图的单行,因为Neo4j没有对子图查询的本机支持。
特别是过程apoc.path.subgraphNodes()
有助于从每个节点扩展到整个子图,并且只计算到每个节点的单个路径,而不是评估所有可能的路径。
从那里,我们可以通过子图中的最小节点进行分组,并且只保留一组代表整个子图的节点。这使我们每个子图获得一行,这使得我们的谓词可以检查子图中所有节点的颜色,每个子图只运行一次。
这样的事情:
MATCH (n:BLUE) // no need to get subgraphs that don't have blue nodes
CALL apoc.path.subgraphNodes(n, {}) YIELD node
WITH n, collect(node) as nodes, min(id(node)) as minId
WITH minId, head(collect(nodes)) as nodes // now only one row / subgraph
WHERE all(node in nodes where node:BLUE)
UNWIND nodes as node
SET node:RED
REMOVE node:BLUE