我正在使用 Neo4j 图形数据库,其中有特定类型的节点,我们将其称为设备。每个设备节点都有一个类型属性,可以是“A”、“B”或“C”。节点以单一类型的双向关系连接。
我需要找到图中以“B”类型节点开始和结束的所有循环,条件是其间的每个步骤仅通过“C”类型节点连接。
这是我提出的 Cypher 查询:
MATCH (start:Device {type: "B"})
CALL apoc.path.expandConfig(start, {
relationshipFilter: "CONNECTED_TO>",
labelFilter: ">Device",
minLevel: 1,
maxLevel: 9999,
uniqueness: 'NODE_PATH'
}) YIELD path
WHERE LENGTH(path) >= 3
AND ALL(node IN nodes(path)[1..-1] WHERE node.type = "C")
AND last(nodes(path)).type = 'B'
AND id(start) <= id(last(nodes(path)))
RETURN path
此查询有效,但速度很慢 — 对于具有 200 个节点和 800 个关系的图,需要花费 20 秒以上。如何优化此查询以更有效地运行?
我找到了解决问题的方法。由于我的要求非常具体,因此我决定为每种类型创建不同的节点标签,而不是创建具有不同“类型”属性的相同类型的节点。然后,我使用 apoc.path.expandConfig 函数中的 labelFilter 参数来相应地过滤节点。以下是我修改 Cypher 查询的方法:
MATCH (start:B_Device)
CALL apoc.path.expandConfig(start, {
relationshipFilter: "CONNECTED_TO>",
labelFilter: "+C_Device|/B_Device",
minLevel: 1,
maxLevel: 9999,
uniqueness: 'NODE_PATH'
}) YIELD path
WHERE LENGTH(path) >= 3
AND ALL(node IN nodes(path)[1..-1] WHERE node.type = "C")
AND last(nodes(path)).type = 'B'
AND id(start) <= id(last(nodes(path)))
RETURN path
此修改将执行时间从超过 20 秒减少到不到 1 毫秒。令人难以置信的进步!