Neo4j索引插入Where子句中

问题描述 投票:0回答:1

我有一个neo4j数据库,其中包含带有标签User的节点。在User.user_id属性上建立索引。

执行以下查询确实使用索引:

MATCH (u:User)
WHERE u.user_id = 1234
RETURN u

但是,按如下方式修改查询时,跨越所有记录以检索所需记录的索引将被完全忽略:

MATCH (u:User)
WHERE 1234 is null OR u.user_id = 1234
RETURN u

这种查询的用例是使用多个可选参数进行过滤,例如:

MATCH (u:User)
WHERE ({user_id} is null OR u.user_id = {user_id})
AND   ({status} is null or u.status = {status})
AND   ({name} is null or u.name = {})
RETURN u

我们如何解释neo4j中的这种行为,而没有变通办法,有哪些可能的修复方法?

neo4j cypher graph-databases graphdb
1个回答
0
投票

查询计划的构建独立于参数求值(请记住查询计划已缓存和重用,因此它不是基于每个查询的,因此在查询计划期间,如下所示:

MATCH (u:User)
WHERE ({user_id} is null OR u.user_id = {user_id})
...

在实际执行索引查找或标签扫描之前没有办法知道,因此默认为标签扫描操作。

作为一种解决方法,您可以使用APOC conditional procedures来执行条件Cypher:

CALL apoc.case([$user_id is not null, "MATCH (u:User {user_id : $user_id} RETURN u", $name is not null, "MATCH (u:User {name:$name}) RETURN u", $status is not null, "MATCH (u:User {status:$status}) RETURN u"], "MATCH (u:User) RETURN u", {user_id:$user_id, name:$name, status:$status}) YIELD value
WITH value.u as u
WHERE ($status is null or u.status = $status)
AND   ($name is null or u.name = $name)
...

[如果确实触发了第一个条件以允许对user_id索引进行查找,或者如果触发了第二个条件而允许进行了名称索引查找,则您确实需要保留状态和名称检查,您仍然希望对其余条件进行过滤。

或者,您可以在使用驱动程序的代码中处理此问题,根据您拥有的参数组装或选择要运行的查询。这将使复杂性降低,效率更高。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.