Cypher Neo4j查询优化

时间:2018-01-11 14:24:13

标签: neo4j cypher

我使用以下Cypher查询:

MATCH (v:Value)-[:CONTAINS]->(hv:HistoryValue) 
WHERE v.id = {valueId} 
OPTIONAL MATCH (hv)-[:CREATED_BY]->(u:User) 
WHERE {fetchCreateUsers} 
WITH u, hv 
ORDER BY hv.createDate DESC 
WITH count(hv) as count, ceil(toFloat(count(hv)) / {maxResults}) as step, COLLECT({userId: u.id, historyValueId: hv.id, historyValue: hv.originalValue, historyValueCreateDate: hv.createDate}) AS data 
RETURN REDUCE(s = [], i IN RANGE(0, count - 1, CASE step WHEN 0 THEN 1 ELSE step END) | s + data[i]) AS result, step, count

这个查询工作正常,完全符合我的需要。

现在,我从性能的角度和Cypher最佳实践中关注此查询中的两个可能问题。

首先,正如您所看到的 - 我两次使用相同的count(hv)函数。从性能的角度来看,它是否会导致执行期间的问题,或者Cypher和Neo4j是否足够聪明以优化它?如果不是,请说明如何修复它。

第二位是range()函数中的CASE语句?同样的问题 - 这个CASE语句只会在我的范围内的每次迭代中执行一次或每次执行吗?如果需要,请说明如何修复它。

已更新

我尝试为计数执行分隔符WITH,但查询没有返回结果(返回空结果)

MATCH (v:Value)-[:CONTAINS]->(hv:HistoryValue) 
WHERE v.id = {valueId} 
OPTIONAL MATCH (hv)-[:CREATED_BY]->(u:User) 
WHERE {fetchCreateUsers} 
WITH u, hv ORDER BY hv.createDate DESC 
WITH u, hv, count(hv) as count 
WITH u, hv, count, ceil(toFloat(count) / {maxResults}) as step, COLLECT({userId: u.id, historyValueId: hv.id, historyValue: hv.originalValue, historyValueCreateDate: hv.createDate}) AS data 
RETURN REDUCE(s = [], i IN RANGE(0, count - 1, CASE step WHEN 0 THEN 1 ELSE step END) | s + data[i]) AS result, step, count

1 个答案:

答案 0 :(得分:1)

1 MATCH (v:Value)-[:CONTAINS]->(hv:HistoryValue) 
2 WHERE v.id = {valueId} 
3 OPTIONAL MATCH (hv)-[:CREATED_BY]->(u:User) 
4 WHERE {fetchCreateUsers} 
5 WITH u, hv 
6 ORDER BY hv.createDate DESC 
7 WITH count(hv) as count, ceil(toFloat(count(hv)) / {maxResults}) as step, COLLECT({userId: u.id, historyValueId: hv.id, historyValue: hv.originalValue, historyValueCreateDate: hv.createDate}) AS data 
8 RETURN REDUCE(s = [], i IN RANGE(0, count - 1, CASE step WHEN 0 THEN 1 ELSE step END) | s + data[i]) AS result, step, count

(1)您需要在第5行传递hv,因为它的值会在第7行收集。也就是说,您仍然可以执行以下操作:

5 WITH u, collect(hv) AS hvs, count(hv) as count
  UNWIND hvs AS hv

然而,这不是很优雅,可能不值得。

(2)您可以在第7行计算CASE表达式:

7 WITH count, data, step, CASE step WHEN 0 THEN 1 ELSE step END AS stepFlag
8 RETURN REDUCE(s = [], i IN RANGE(0, count - 1, stepFlag) | s + data[i]) AS result, step, count