Есть несколько способов сделать это.
В этой модели одним способом является сбор узлов по траектории и использование предикатов списка, включающих только те траектории, в которых отсутствуют какие-либо требуемые позиции:
MATCH (t:Trajectory)-[:CONTAINS]->(p)
WITH t, collect(DISTINCT p.pos) as pointPositions
WHERE size(pointPositions) < 3 OR any(required in ['START', 'END', 'MIDDLE'] WHERE NOT required IN pointPositions)
RETURN t
Обратите внимание, что если вы реорганизуете свою модель таким образом, чтобы вместо нее указывалось положение точки, например:
(:Trajectory)-[:HAS_START]->(:Point)
(:Trajectory)-[:HAS_END]->(:Point)
(:Trajectory)-[:HAS_MIDDLE]->(:Point)
Тогда ваш запрос будет немного проще, а эффективность улучшится (что покажет наибольшую выгоду, когда у вас много траекторий, некоторые со множеством подключенных узлов).
MATCH (t:Trajectory)
WHERE NOT (t)-[:HAS_START]->() OR NOT (t)-[:HAS_END]->() OR NOT (t)-[:HAS_MIDDLE]->()
RETURN t
При таком моделировании и такого рода запросах нам даже не нужно расширяться от узлов траектории, чтобы получить наш ответ, поскольку узел знает, какие отношения связаны с ним (по типу и / или направлению) и их количество , Тогда очень легко определить, существуют ли определенные типы отношений.