Neo4J Cypher условное выражение where в зависимости от параметра

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

У меня есть узлы под названием KnowledgeEntry, к которым прикреплено несколько записей KnowledgeRecords.

(:KnowledgeEntry)-[:CONTAINS]->(:KnowledgeRecord)

Каждый KnowledgeRecords имеет четыре типа отношений с узлами типа Location, Community, Function или OrganizationalUnit, каждый из которых имеет атрибут id.

Я хочу получить все KnowledgeEntries, если у них есть одна или несколько KnowledgeRecords, которые имеют отношение к Location, Community, Function или OU, где id соответствует одному из элементов в данном списке (параметр)

Вот что я до сих пор придумал:

MATCH (knowledgeEntry:KnowledgeEntry)-[relationship]-(:KnowledgeEntry)
WHERE EXISTS {
    MATCH (knowledgeEntry)-[:CONTAINS]->(:KnowledgeRecord)-[:BASED_AT]->(loc:Location)
    WHERE loc.id IN $filters.locationIds
}

RETURN relationship, knowledgeEntry;

Это работает, только если установлены все используемые параметры. Если, например, $ filters.locationIds не имеет записей или имеет значение null, оператор where следует игнорировать. Я пробовал это с помощью оператора CASE и apoc.when, но безуспешно.

При добавлении OR EXISTS, например, для OrganizationalUnit, я получаю сообщение об ошибке «Должно быть хотя бы одно выражение шаблона»

MATCH (knowledgeEntry:KnowledgeEntry)-[relationship]-(:KnowledgeEntry)
WHERE EXISTS {
    MATCH (knowledgeEntry)-[:CONTAINS]->(:KnowledgeRecord)-[:BASED_AT]->(loc:Location)
    WHERE loc.id IN $locationIds
}

OR EXISTS {
    MATCH (knowledgeEntry)-[:CONTAINS]->(:KnowledgeRecord)-[:RELEVANT_FOR_EMPLOYEES_WITH]->(ou:OrganizationalUnit)
    WHERE ou.id IN $organizationalUnitIds
}

RETURN relationship, knowledgeEntry;

person Timo Jokinen    schedule 18.02.2020    source источник


Ответы (1)


Похоже, вы столкнулись с возможной ошибкой neo4j при наличии нескольких экзистенциальные подзапросы в логическом выражении.

Этот запрос объединяет ваши два подзапроса и может лучше работать для вас:

MATCH (knowledgeEntry:KnowledgeEntry)-[relationship]-(:KnowledgeEntry)
WHERE EXISTS {
  MATCH (knowledgeEntry)-[:CONTAINS]->(:KnowledgeRecord)-[:BASED_AT|RELEVANT_FOR_EMPLOYEES_WITH]->(x)
  WHERE
    (x:OrganizationalUnit AND x.id IN $organizationalUnitIds) OR
    (x:Location AND x.id IN $locationIds)
}
RETURN relationship, knowledgeEntry;
person cybersam    schedule 18.02.2020