План запроса строится независимо от оценки параметров (помните, что планы запросов кэшируются и используются повторно, поэтому он не относится к отдельным запросам), поэтому во время планирования такого запроса:
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.