基于上一个问题:
Neo4j Cypher query structure and performance optimization Neo4j Cypher node filtering by pattern comprehension
最后我将我的查询重构为以下内容:
MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE id(parentD) = {decisionId}
MATCH (childD)<-[:SET_FOR]-(equalFilterValue)-[:SET_ON]->(equalFilterCharacteristic)
WHERE ALL(key IN keys({equalFilters}) WHERE id(equalFilterCharacteristic) = toInt(key) AND equalFilterValue.value = ({equalFilters}[key]))
WITH DISTINCT childD
MATCH (childD)<-[:SET_FOR]-(rangeFilterValue)-[:SET_ON]->(rangeFilterCharacteristic)
WHERE ALL(key IN keys({rangeFilters}) WHERE id(rangeFilterCharacteristic) = toInt(key) AND ({rangeFilters}[key])[0] <= rangeFilterValue.value <= ({rangeFilters}[key])[1])
WITH * MATCH (childD)-[ru:CREATED_BY]->(u:User)
RETURN ru, u, childD AS decision
SKIP 0 LIMIT 100
如果每个*filter
类型(地图)只有一个键,则此查询可以正常工作,例如:
queries.add(new InQuery(integerCharacteristic.getId(), 30));
或
queries.add(new InQuery(stringCharacteristic.getId(), "Two"));
但是当我添加2个或更多条件时失败,例如:
queries.add(new InQuery(integerCharacteristic.getId(), 30));
queries.add(new InQuery(stringCharacteristic.getId(), "Two"));
以下查询没有按预期工作,我的测试断言失败:
MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE id(parentD) = {decisionId}
MATCH (childD)<-[:SET_FOR]-(inFilterValue)-[:SET_ON]->(inFilterCharacteristic)
WHERE ALL(key IN keys({inFilters}) WHERE id(inFilterCharacteristic) = toInt(key) AND ({inFilters}[key]) IN inFilterValue.value)
WITH * MATCH (childD)-[ru:CREATED_BY]->(u:User)
RETURN ru, u, childD AS decision
SKIP 0 LIMIT 100
参数:
inFilters = {3153=30, 3151=Two}
当inFilters
地图包含2个或更多密钥以及如何使其有效时,为什么它不起作用?
答案 0 :(得分:1)
因此,这只适用于1个键,让我们看看当有2个键时WHERE ALL正在做什么。
WITH inFilters = {3153=30, 3151=Two}
....
WHERE ALL(key IN keys({equalFilters})
WHERE id(equalFilterCharacteristic) = toInt(key)
AND equalFilterValue.value = ({equalFilters}[key]))
相当于
WHERE id(equalFilterCharacteristic) = toInt(3153)
AND equalFilterValue.value = ({equalFilters}[3153])
AND id(equalFilterCharacteristic) = toInt(3151)
AND equalFilterValue.value = ({equalFilters}[3151])
现在的问题是,现在我们正在检查equalFilterCharacteristic的节点id是否同时等于3153 AND 3151,对于每个equalFilterCharacteristic。由于Neo4j仅对节点ID使用实数,因此当存在多于1个键时,上述语句基本上最终会减少为昂贵的WHERE FALSE。因此,在上述情况下,所有情况都不可能成立。但是,如果至少有1个check-group为真,那么它将评估为true,并且等同于
WHERE (
id(equalFilterCharacteristic) = toInt(3153)
AND equalFilterValue.value = ({equalFilters}[3153])
)
OR
(
id(equalFilterCharacteristic) = toInt(3151)
AND equalFilterValue.value = ({equalFilters}[3151])
)
当然,既然你知道你要匹配的密钥,你可以跳过ALL而只是做(不要认为你需要id()上的Int(),但是id()很长)
WHERE equalFilterValue.value = ({equalFilters}[id(equalFilterCharacteristic)])