В этом случае я предлагаю, чтобы каждый: узел каталога имел полный путь в качестве свойства, это упростит сопоставление с каталогами и их путями:
MATCH path = (:Root)-[:CONTAINS*]->(d:Directory)
WITH d, [node in tail(nodes(path)) | node.name] as directories
WITH d, apoc.text.join(directories, '/') as pathString
SET d.path = pathString
(вы можете использовать аналогичный запрос дляобновить каталог (и его дочерние элементы) в случаях, когда каталог перемещается в дереве)
С помощью этого набора он позволяет легко сопоставить конечный узел пути, даже если вы не предоставляетечасть пути над интересующим путем (вы не упомянули, всегда ли указанный вами путь простирается от корня или это просто конец пути):
WITH 'dir A/dir D/dir G' as inputString
MATCH (end:Directory)
WHERE end.path ENDS WITH inputString
RETURN end
Так что если :DIRECTORY(path)
индексируется, тогда у вас есть быстрый доступ к конечному узлу. Теперь, чтобы найти другие.
Мы можем использовать выражение пути переменной длины, чтобы найти полный путь этих узлов, используя предикат all()
, чтобы гарантировать, что каждый узел в пути имеет имя из входных данных разделенияи это проверяется при расширении. Это дает нам пути к нужным нам узлам (тратит впустую только один дополнительный обход к родительскому элементу выше), но это не гарантирует порядок, мы должны фильтровать это после.
Это должно работать с вашимпример графика:
WITH 'dir A/dir D/dir G' as inputString
WITH inputString, split(inputString, '/') as dirNames
MATCH (end:Directory)
WHERE end.path ENDS WITH inputString
MATCH path = (start)-[:CONTAINS*]->(end)
WHERE all(node in nodes(path) WHERE node.name IN dirNames)
WITH path
WHERE length(path) + 1 = size(dirNames) AND [node in nodes(path) | node.name] = dirNames
RETURN path