Создание вашей модели
Для простоты возможных дальнейших ответов и решений отмечу мое утверждение создания графа:
CREATE
(ormText:OrmText {name: 'orm_Text'})<-[:FIRST_CHILD_OF]-(letterA:Letter {name: 'A'}),
(letterA)-[:NEXT]->(letterB:Letter {name: 'B'}),
(letterA)-[:NEXT_SIBLING]->(letterB),
(letterB)-[:NEXT]->(letterC:Letter {name: 'C'}),
(letterB)-[:NEXT_SIBLING]->(letterC),
(letterC)-[:NEXT]->(letterD:Letter {name: 'D'}),
(letterC)-[:NEXT_SIBLING]->(letterD),
(letterD)-[:LAST_CHILD_OF]->(ormText);
Решение
MATCH
letterPath = (startLetter)-[:NEXT|NEXT_SIBLING*]->(endLetter)
WHERE
(startLetter)-[:FIRST_CHILD_OF]->(:OrmText)<-[:LAST_CHILD_OF]-(endLetter)
WITH nodes(letterPath) AS letterNodes
UNWIND letterNodes AS letterNode
RETURN DISTINCT letterNode.name AS letterName;
Вторая строка определяет startLetter
как первый дочерний элемент orm_Text
и endLetter
как последний дочерний элемент orm_Text
.
В пятой строке вычисляется путь между начальной и конечной буквой, его узлы извлечены в шестой строке. Строка семь создает одиночные узлы, а строка восемь, наконец, возвращает результат.
Примечание: При написании -[:NEXT|NEX_SIBLING*]->
отношение типа NEXT
или NEXT_SIBLING
действительно для совпадения. Если вашему требованию нужен только один конкретный тип, удалите другой и |
.
Результат
╒════════════╕
│"letterName"│
╞════════════╡
│"A" │
├────────────┤
│"B" │
├────────────┤
│"C" │
├────────────┤
│"D" │
└────────────┘
Extension
Если вы предпочитаете вывод в одном String
вместо списка имен узлов, взгляните на следующее решение.
Решение
MATCH
letterPath = (startLetter)-[:NEXT|NEXT_SIBLING*]->(endLetter)
WHERE
(startLetter)-[:FIRST_CHILD_OF]->(:OrmText)<-[:LAST_CHILD_OF]-(endLetter)
WITH nodes(letterPath) AS letterNodes
RETURN DISTINCT reduce(s=head(letterNodes).name, n in tail(letterNodes) | s+" -> "+n.name) AS letterString;
Результат
╒══════════════════╕
│"letterString" │
╞══════════════════╡
│"A -> B -> C -> D"│
└──────────────────┘