Рассмотрите следующие узлы, которые связаны между собой двумя типами ребер: прямые и пересекающиеся. Запрос должен обнаружить все возможные пути между 2 узлами, который удовлетворяет все следующие правила:Neo4j: совпадение с множественными отношениями своевременно
- 0..n прямых края
- 0..1 пересекаться краем
- пересекаться краем может быть между прямыми краями
Эти пути считаются действительными между nodeZ и узла а:
(nodeA)-[:direct]->(nodeB)-[:direct]->(nodeC)->[:direct]->(nodeZ)
(nodeA)-[:intersect]->(nodeB)-[:direct]->(nodeC)->[:direct]->(nodeZ)
(nodeA)-[:direct]->(nodeB)-[:intersect]->(nodeC)->[:direct]->(nodeZ)
(nodeA)-[:direct]->(nodeB)->[:direct]->(nodeC)-[:intersect]->(nodeZ)
В основном пересекаются край может произойти где угодно в пути, но только один раз. Мой идеальный монограмма запрос в несуществующей версии Neo4j бы это:.
MATCH (from)-[:direct*0..N|:intersect*0..1]->(to)
Но Neo4j не поддерживает несколько ограничений для типа ребер :(
UPDATE 23.04.16
Здесь 6609 узлов (из общего объема 550 тыс.), 5184 краев типа прямого (всего 440 тыс.) И 34119 типа пересекаются (из общего количества 37289). Ожидаются некоторые циклические ссылки (которые избегают нео-4j, не так ли ?)
Запрос, который выглядел многообещающим, но не смог закончить в манере секунд:
MATCH p = (from {from: 1})-[:direct|intersect*0..]->(to {to: 99}) WHERE 123 < from.departureTS < 123 + 86400 //next day AND REDUCE(s = 0, x IN RELATIONSHIPS(p) | CASE TYPE(x) WHEN 'intersect' THEN s + 1 ELSE s END) <= 1 return p;
Ваш запрос не соответствует указанным требованиям. Он возвращает только пути, начинающиеся по крайней мере с одного «прямого», за которым следует «пересечение», за которым следует, по крайней мере, один «прямой» в конце.Вы можете изменить его, чтобы правильно работать (но это может быть не так хорошо, как мой ответ): 'MATCH p = ((from) - [: direct * 0 ..] -> (middle) - [: intersect * 0. .1] -> (middle2) - [: direct * 0 ..] -> (to)) return DISTINCT p; ' – cybersam
Единственное требование, которое это имеет, состоит в том, что на графике существует пересекающееся ребро, которое это делает. Если ребро пересечения также необязательно, то [: intersect] можно заменить на [: intersect *]. –
'intersect' не требуется [0..1], а также' direct' [0..N]. И нет требования, чтобы путь должен начинаться и заканчиваться «прямым». – cybersam