Обрезка общего дерева с использованием шифра - PullRequest
0 голосов
/ 26 июня 2019

Имеется база данных neo4j, содержащая вершины типа папок или листов.Общее дерево моделируется с использованием отношений childof, и существует один «корневой» узел, который является общим предком для всех вершин.

При представлении дерева я хочу отфильтровать полные ветви на основеидентификатор любой вершины типа папка.Дополнительно есть фильтр для любых свойств на вершинах типа лист.Сложность в том, что я не хочу видеть папки, в которых отфильтрованы все нисходящие конечные узлы.Каждый запрос возвращает только непосредственных потомков, но фильтр применяется ко всему поддереву.Запрос должен возвращать непосредственные дочерние элементы и коллекцию идентификаторов каждой папки, содержащей листы, которые не отфильтрованы.

Вариант использования - это API для отображения иерархии, основанной на некоторых ограничениях фильтра.Я запрограммировал это в коде приложения API, но передача всех данных из базы данных в приложение API выполняется слишком медленно, поэтому мне нужно улучшить запрос, чтобы сжать передачу данных.Третий подход - использование специально созданного процесса, который выполняет эту фильтрацию, сохраняя дерево в памяти.Это было сделано с некоторым успехом, но я предпочитаю использовать полки, если смогу.

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

MATCH (p)-[:childof]->(s:Folder) WHERE s.name = 'root'
WITH p OPTIONAL MATCH (v)-[:childof*1..]->(p)
WHERE NOT((v)<-[:childof]-(:Folder))
RETURN p, collect(v.id) as folder_ids

Моя личная склонность к проблеме заключается в том, что он слишком специфичен для графического движка общего назначения, но я надеюсь, что он окажется неверным.

1 Ответ

1 голос
/ 26 июня 2019

Звучит так, будто ты рядом.

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

Ина уровне прямого потомка, если мы используем MATCH вместо OPTIONAL MATCH, так как папки будут фильтроваться для вас, единственные оставшиеся непосредственные потомки - это те, у которых есть хотя бы одна из этих папок.

Допустим,Например, наш фильтр состоит в том, что конечные узлы должны иметь active = true, поэтому мы хотим убедиться, что у наших папок для рассмотрения должен быть хотя бы один дочерний узел, соответствующий фильтру, и когда мы вернемся к непосредственным потомкам, нам нужно толькосохранить этот потомок, если коллекция подходящих папок не пуста.

Примерно так:

MATCH (p)-[:childof]->(s:Folder) WHERE s.name = 'root'
WITH p 
MATCH (folder)-[:childof*1..]->(p)
WHERE NOT((folder)<-[:childof]-(:Folder)) AND 
  size([(folder)<-[:childof]-(child) WHERE child.active = true | child]) <> 0
RETURN p, collect(folder.id) as folder_ids
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...