大家好,我目前正在尝试编写一个cypher语句,允许我从起点找到地图上的一组路径。 我希望我的搜索结果始终返回5个节点内的连接街道。或者,如果附近有医院,我希望我的搜索模式也能指示附近的医院。
因为当前街道附近的医院并不总是,有时我的可选匹配搜索模式会返回为空。这是我目前使用的密码声明:
MATCH path=(a:Street {id: 123})-[:CONNECTED_TO*..5]-(b:Street)
OPTIONAL MATCH optionalPath=(b)-[:CONNECTED_TO]->(hospital:Hospital)
WHERE ALL (x IN nodes(path) WHERE (x:Street))
WITH DISTINCT nodes(path) + nodes(optionalPath) as n
UNWIND n as nodes
RETURN DISTINCT nodes;
但是,此语法仅在 optionalPath
包含节点时才有效。如果它没有,则语句nodes(path) + nodes(optionalPath)
是一个添加null的操作,我没有记录。即使nodes(path)
术语确实包含节点,也是如此。
解决此问题的最佳方法是什么?
答案 0 :(得分:2)
您可以使用COALESCE
将NULL
替换为其他值。例如:
MATCH path=(:Street {id: 123})-[:CONNECTED_TO*..5]-(b:Street)
WHERE ALL (x IN nodes(path) WHERE x:Street)
OPTIONAL MATCH optionalPath=(b)-[:CONNECTED_TO]->(hospital:Hospital)
WITH nodes(path) + COALESCE(nodes(optionalPath), []) as n
UNWIND n as nodes
RETURN DISTINCT nodes;
我还做了一些其他改进:
WHERE
子句在第一个MATCH
之后立即上移。这会立即消除不需要的path
值。您的原始查询将获得所有path
值(甚至是不需要的值),并始终执行第二个MATCH
查询,并且之后只消除不需要的路径。 (但是,实际上并不清楚您是否甚至需要WHERE
子句;例如,如果CONNECTED_TO
关系仅用于Street
个节点之间。)
DISTINCT
子句中的WITH
会阻止重复的n
个集合,但内部集合可能有重复的路径。这可能不是你想要的。
答案 1 :(得分:0)
您似乎并不真正想要这条路,只需5步内的所有街道节点,再加上任何连接的医院。所以我会简化你的查询,然后将3列压缩为1。
MATCH (a:Street {id: 123})-[:CONNECTED_TO*..5]-(b:Street)
OPTIONAL MATCH (b)-[:CONNECTED_TO]->(hospital:Hospital)
WITH collect(a) + collect(b) + collect(hospital) as n
UNWIND n as nodez
RETURN DISTINCT nodez;
如果Streets可以间接连接(介于两者之间的医院),那么我可以像这样调整
MATCH (a:Street {id: 123})-[:CONNECTED_TO]-(b:Street)
WITH a as nodez, b as a
MATCH (a)-[:CONNECTED_TO]-(b:Street)
WITH nodez+collect(b) as nodez, b as a
MATCH (a)-[:CONNECTED_TO]-(b:Street)
WITH nodez+collect(b) as nodez, b as a
MATCH (a)-[:CONNECTED_TO]-(b:Street)
WITH nodez+collect(b) as nodez, b as a
MATCH (a)-[:CONNECTED_TO]-(b:Street)
WITH nodez+collect(b) as nodez, b as a
OPTIONAL MATCH (b)-[:CONNECTED_TO]->(hospital:Hospital)
WITH nodez + collect(hospital) as n
UNWIND n as nodez
RETURN DISTINCT nodez;
它有点冗长,但只是准确地说出你想要的东西(并且还将起始节点添加到医院检查清单)