基于地图参数的Neo4j Cypher过滤 [英] Neo4j Cypher filtering based on map parameters

查看:77
本文介绍了基于地图参数的Neo4j Cypher过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于上一个问题:

Neo4j Cypher查询结构和性能优化 通过模式理解对Neo4j Cypher节点进行过滤

最后,我将查询重构为以下内容:

finally I have refactored my query to the following:

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类型(地图)只有一个键,则此查询工作正常,例如:

This query works fine if each *filter type(map) has only one key, for example:

queries.add(new InQuery(integerCharacteristic.getId(), 30));

queries.add(new InQuery(stringCharacteristic.getId(), "Two"));

但是在添加两个或多个条件时失败,例如:

but fails when I add 2 or more conditions, for example:

queries.add(new InQuery(integerCharacteristic.getId(), 30));
queries.add(new InQuery(stringCharacteristic.getId(), "Two"));

以下查询无法按预期运行,并且我的测试断言失败:

The following query doesn't work as expected and my test assertions fail:

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个或更多键时为什么不起作用以及如何使其起作用?

Why it doesn't work when inFilters map contains 2 or more keys and how to make it working ?

推荐答案

因此,由于它仅适用于1个键,因此,让我们回顾一下当有2个键时WHERE ALL正在进行的操作.

So for the reason this only works with 1 key, lets go over what one WHERE ALL is doing when there is 2 keys.

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是否同时等于每一个equalFilterCharacteristic的3153 AND 3151.由于Neo4j仅对节点ID使用实数,因此,当密钥数超过1个时,以上语句基本上最终减少为昂贵的WHERE FALSE.因此,在上述情况下,WHERE ALL永远不可能是正确的.但是,如果至少有1个检查组为true,则WHERE ANY的结果将为true,并且等效于

And the problem there is that now we are checking that the node id of equalFilterCharacteristic is equal to 3153 AND 3151 at the same time, for each and every equalFilterCharacteristic. Since Neo4j only uses real numbers for the node ids, the above statement basically ends up reducing to an expensive WHERE FALSE when there is more than 1 key. So WHERE ALL can never be true in the above case. WHERE ANY however will evaluate to true if at least 1 check-group is true, and would be equivalent to

WHERE ( 
    id(equalFilterCharacteristic) = toInt(3153) 
    AND equalFilterValue.value = ({equalFilters}[3153]) 
)
OR 
(
    id(equalFilterCharacteristic) = toInt(3151) 
    AND equalFilterValue.value = ({equalFilters}[3151]) 
)

当然,由于您知道要匹配的密钥,因此可以跳过所有内容而只是这样做(不要认为您需要对id()进行toInt(),但id()很长)

Of course, since you know the key you are trying to match, you can skip the ALL and just do (don't think you need toInt() on id(), but id() is a long)

WHERE equalFilterValue.value = ({equalFilters}[id(equalFilterCharacteristic)]) 

这篇关于基于地图参数的Neo4j Cypher过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆