Neo4j Cypher基于map参数进行过滤

时间:2017-05-11 06:31:11

标签: neo4j cypher

基于上一个问题:

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个或更多密钥以及如何使其有效时,为什么它不起作用?

1 个答案:

答案 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)])