Индекс Neo4j, указанный в предложении Where - PullRequest
0 голосов
/ 24 марта 2020

У меня есть база данных neo4j, содержащая узлы с меткой Пользователь . Индекс создается для свойства 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 и каковы возможные исправления без обходных путей?

1 Ответ

0 голосов
/ 24 марта 2020

План запроса строится независимо от оценки параметров (помните, что планы запросов кэшируются и используются повторно, поэтому он не относится к отдельным запросам), поэтому во время планирования такого запроса:

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

нет способа узнать, прежде чем на самом деле выполнить, следует ли использовать поиск индекса или сканирование метки, поэтому по умолчанию используется операция сканирования метки.

В качестве обходного пути вы можете использовать APO C условные процедуры , которые позволяют вам выполнять условный шифр:

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, или в случае, если было запущено второе условие, разрешающее поиск по индексу имен, вы все равно хотите отфильтровать остальные.

В качестве альтернативы вы можете обработать это в своем коде, который использует драйвер, либо собирая, либо выбирая запрос, который вы хотите выполнить на основе параметров у вас есть. Это сделало бы менее сложным и более эффективным Cypher.

...