Neo4j: перебирая от листа к родителю И находя общих детей - PullRequest
0 голосов
/ 10 декабря 2018

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

Мне нужны следующие функции: 1) Я запустил скрипт для назначения: метки листа всем узлам, которые являются листьями в моем дереве.В путях между известным узлом и связанными с ним конечными узлами я стремлюсь назначить каждому узлу свойство уровня, которое отражает количество прыжков этого узла от известного узла (или конечного узла - все, что я могу получить, чтобы работать наиболее легко).

Я пробовал: match path=(n:Leaf)-[:R*]->(:Parent {Parent_ID: $known_value}) with n, length(nodes(path)) as hops set n.Level2=hops;

и path=(n:Leaf)-[:R*]->(:Parent {Parent_ID: $known_value}) with n, path, length(nodes(path)) as hops foreach (n IN relationships (path) | set n.Level=hops);

Первый присваивает свойство со значением полной длины пути только конечным узлам.Второй присваивает свойство со значением полной длины пути всем отношениям в пути.

Стоит ли вместо этого использовать кратчайший путь, создать фиктивное свойство со значением = 1 для всех узлов и итеративно добавить вес этого свойства?

2) Мне нужно найти общих потомков для данного родительского узла.Например, у моих детей каждый [: like] много фильмов, и я хотел бы создать [: like] отношения от себя до тех фильмов, которые всем моим детям нравятся вместе (поэтому, если 1 из 1 любит фильм, то янравится тоже, но если только 2 из 3, как фильм, ничего не происходит).

Я нашел решение с тремя путями здесь: Нужны только общие узлы на нескольких путях - Neo4j Cypher НоМне нужно решение, которое работает для любого числа путей (начиная с 1).

3) Затем я планирую начать с моих самых дальних конечных узлов, создать отношения с детскими фильмами и постепенно переходить к моим известнымповторяйте узлы и создавайте отношения так, чтобы самый старший дедушка любил только фильмы, которые нравятся всем детям [всех детей всех детей ...], и если есть один, с которым все согласны, это фильм всей расширенной семьибудем смотреть в субботу вечером.

Можно ли это сделать с помощью neo4j, и насколько трудной является задача для кого-то с элементарным Cypher?Это в основном то, как я это сделал в своей реляционной базе данных. Должен ли я смотреть на реализацию этого совершенно иначе в графовой базе данных?

Самый благодарен за любой совет.Спасибо!

1 Ответ

0 голосов
/ 10 декабря 2018

1.

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

Обычно при установкечто-то вроде глубины узла в дереве, вы должны использовать length(path), поэтому корень будет на глубине 0, а его дочерние элементы - на глубине 1.

Обычно глубина рассчитывается относительно корневого узла ине листовые узлы (поскольку промежуточный узел может быть предком множества листовых узлов на разных расстояниях).Использование глубины в качестве расстояния от корня делает глубины согласованными.

Ваш подход с установкой свойства для отношений будет проблемой, так как одни и те же отношения могут присутствовать в нескольких путях для нескольких конечных узлов на различной глубине.,Ваш запрос может перезаписывать свойство одних и тех же отношений снова и снова, пока не победит последняя запись.Было бы лучше сопоставить все узлы (пропустить :Leaf в запросе), взять последнее отношение в пути и установить его глубину:

MATCH path=(:Parent {Parent_ID: $known_value})<-[:R*]-()
WITH length(path) as length, last(relationships(path)) as rel
SET rel.Level = length

2.

Итак, если все дочерние узлы родителя в дереве: как в фильме, тогда родитель должен: как в фильме.Примерно так должно работать:

MATCH path=(:Parent {Parent_ID: $known_value})<-[:R*0..]-(n)
WITH n, size((n)<-[:R]-()) as childCount
MATCH (n)<-[:R]-()-[:like]->(m:Movie)
WITH n, childCount, m, count(m) as movieLikes
WHERE childCount = movieLikes
MERGE (n)-[:like]->(m)

Идея здесь в том, что для фильма, если количество узлов этого фильма равно количеству дочерних узлов, тогда всем детям понравился фильм (при условии, чтоузел может только: как один и тот же фильм один раз).

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

3.

Чтобы выполнить восходящий подход, вам необходимопринудительно выполнить запрос в определенном порядке, и я считаю, что лучший способ сделать это - сначала упорядочить узлы для обработки в глубоком порядке, а затем использовать apoc.cypher.doIt () , процесс в Процедуры APOC , которые позволяют выполнить весь запрос Cypher для каждой строки, чтобы выполнить вычисление.

Этот подход должен работать:

MATCH path=(:Parent {Parent_ID: $known_value})<-[:R*0..]-(n)
WHERE NOT n:Leaf // leaves should have :like relationships already created
WITH n, length(path) as depth, size((n)<-[:R]-()) as childCount
ORDER BY depth DESC
CALL apoc.cypher.doIt("
 MATCH (n)<-[:R]-()-[:like]->(m:Movie)
 WITH n, childCount, m, count(m) as movieLikes
 WHERE childCount = movieLikes
 MERGE (n)-[:like]->(m)
 RETURN count(m) as relsCreated",
 {n:n, childCount:childCount}) YIELD value
RETURN sum(value.relsCreated) as relsCreated

Тем не менее, яне уверен, что это будет делать то, что вы тХинк это подойдет.Или, скорее, он будет работать так, как вы думаете, только если: единственные отношения с фильмами изначально устанавливаются только на конечных узлах, и (до запуска этого запроса на распространение) ни один другой промежуточный узел в дереве не имеет: likeотношение к фильму.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...