Cypher COLLECT 使 UNWIND 以错误的顺序展开
Cypher COLLECT makes UNWIND unwind in wrong order
图表要点:http://gist.neo4j.org/?6182d024325343760cb4
我想按顺序获得一条(最长的)路径,它按预期工作,直到我添加 COLLECT 语句,是否有关于 Cypher 和 COLLECT 的东西我只是不明白或者这是一个错误?
此查询按预期工作,returns 路径中的节点顺序正确:
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
RETURN part
这一个,没有 COLLECT 语句,returns 节点顺序正确,而且部件和父节点之间的节点(如预期的那样)。
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(parent)
RETURN part, parent
此查询未按预期工作,returns 路径中的节点以另一种顺序排列:
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(parent)
RETURN part, LAST(COLLECT(parent))
如有任何见解,我们将不胜感激。
UNWIND
实际上仍按预期顺序返回行。相反,它是聚合函数 COLLECT()
,即 "rearranging" 结果行。 neo4j 不保证聚合函数的结果行将以任何特定顺序排列(没有 ORDER BY
子句)。
这是避免使用聚合的解决方法。它可能适用于您的特定用例,具体取决于您的要求。此查询过滤第二个 OPTIONAL MATCH
,以便它包含最长可能的 Has
关系序列(只要最长序列 <= 10 跳——您应该根据需要调整它,或考虑消除最大限度)。查询只是 returns 每个结果行中最远的 "ancestor",并且这些行将保持您期望的顺序。
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(ancestor)
WHERE NOT (ancestor)<-[:Has]-()
RETURN part, ancestor;
图表要点:http://gist.neo4j.org/?6182d024325343760cb4
我想按顺序获得一条(最长的)路径,它按预期工作,直到我添加 COLLECT 语句,是否有关于 Cypher 和 COLLECT 的东西我只是不明白或者这是一个错误?
此查询按预期工作,returns 路径中的节点顺序正确:
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
RETURN part
这一个,没有 COLLECT 语句,returns 节点顺序正确,而且部件和父节点之间的节点(如预期的那样)。
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(parent)
RETURN part, parent
此查询未按预期工作,returns 路径中的节点以另一种顺序排列:
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(parent)
RETURN part, LAST(COLLECT(parent))
如有任何见解,我们将不胜感激。
UNWIND
实际上仍按预期顺序返回行。相反,它是聚合函数 COLLECT()
,即 "rearranging" 结果行。 neo4j 不保证聚合函数的结果行将以任何特定顺序排列(没有 ORDER BY
子句)。
这是避免使用聚合的解决方法。它可能适用于您的特定用例,具体取决于您的要求。此查询过滤第二个 OPTIONAL MATCH
,以便它包含最长可能的 Has
关系序列(只要最长序列 <= 10 跳——您应该根据需要调整它,或考虑消除最大限度)。查询只是 returns 每个结果行中最远的 "ancestor",并且这些行将保持您期望的顺序。
MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(ancestor)
WHERE NOT (ancestor)<-[:Has]-()
RETURN part, ancestor;