Neo4j Cypher查询和集合中元素的索引

时间:2017-11-19 14:50:21

标签: neo4j cypher

我试图通过Decision{decisionGroupId}{decisionId}

找到{criteriaIds}的索引号

这是我目前的Cypher查询:

MATCH (dg:DecisionGroup)-[:CONTAINS]->(childD:Decision) 
WHERE dg.id = {decisionGroupId} 
OPTIONAL MATCH (childD)-[vg:HAS_VOTE_ON]->(c:Criterion) 
WHERE c.id IN {criteriaIds} 
WITH childD, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
ORDER BY weight DESC, totalVotes DESC 
WITH COLLECT(childD) AS ps 
RETURN REDUCE(ix = -1, i IN RANGE(0, SIZE(ps)-1) 
 | CASE ps[i].id WHEN {decisionId} THEN i ELSE ix END) AS ix

我在数据库中只有3个决策,但此查询返回以下索引:

2
3
4

虽然我期待类似的东西(从0开始,如果没有找到-1)

0
1
2

我的查询有什么问题以及如何解决?

已更新

此查询与COLLECT(DISTINCT childD) AS ps

一起正常运行
MATCH (dg:DecisionGroup)-[:CONTAINS]->(childD:Decision) 
WHERE dg.id = {decisionGroupId} 
OPTIONAL MATCH (childD)-[vg:HAS_VOTE_ON]->(c:Criterion) 
WHERE c.id IN {criteriaIds} 
WITH childD, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
ORDER BY weight DESC, totalVotes DESC 
WITH COLLECT(DISTINCT childD) AS ps 
RETURN REDUCE(ix = -1, i IN RANGE(0, SIZE(ps)-1) 
 | CASE ps[i].id WHEN {decisionId} THEN i ELSE ix END) AS ix

请帮我重构一下这个查询,摆脱沉重的REDUCE

2 个答案:

答案 0 :(得分:2)

让我们尝试使用更简单的查询来使reduce部分正确:

WITH ['a', 'b', 'c'] AS ps
RETURN
  reduce(ix = -1, i IN RANGE(0, SIZE(ps)-1) |
    CASE ps[i] WHEN 'b' THEN i ELSE ix END) AS ix
  )

正如我在评论中所说,如果可能,通常最好避免reduce。因此,要使用list comprehension表达相同内容,请使用WHERE进行过滤。

WITH ['a', 'b', 'c'] AS ps
RETURN [i IN RANGE(0, SIZE(ps)-1) WHERE ps[i] = 'b'][0]

列表推导会产生一个包含单个元素的列表,我们将使用[0]索引器来选择该元素。

根据您的查询进行调整后,我们会得到以下内容:

MATCH (dg:DecisionGroup)-[:CONTAINS]->(childD:Decision) 
WHERE dg.id = {decisionGroupId} 
OPTIONAL MATCH (childD)-[vg:HAS_VOTE_ON]->(c:Criterion) 
WHERE c.id IN {criteriaIds} 
WITH childD, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
ORDER BY weight DESC, totalVotes DESC 
WITH COLLECT(DISTINCT childD) AS ps 
RETURN [i IN RANGE(0, SIZE(ps)-1) WHERE ps[i].id = {decisionId}][0]

答案 1 :(得分:2)

如果安装了APOC,您还可以使用以下功能:

return apoc.coll.indexOf([1,2,3],2)