В документах neo4j есть несколько примеров, объясняющих, как писать зашифрованные запросы, относящиеся к диапазонам путей, но интересный вариант, с которым я недавно столкнулся, — это то, где мы хотим найти отдельные переходы в пути.
Я думал, что менеджеры, которые были у «Челси» с момента прихода к власти Романа Абрамовича, послужат полезным набором данных, чтобы показать, как это работает.
Таким образом, мы создаем всех менеджеров и отношения ‘SUCCEEDED_BY’ между ними следующим образом:
CREATE (ranieri {name: "Claudio Ranieri"})
CREATE (mourinho {name: "Jose Mourinho"})
CREATE (grant {name: "Avram Grant"})
CREATE (scolari {name: "Luiz Felipe Scolari"})
CREATE (wilkins {name: "Ray Wilkins"})
CREATE (hiddink {name: "Guus Hiddink"})
CREATE (ancelotti {name: "Carlo Ancelotti"})
CREATE (villasBoas {name: "Andre Villas Boas"})
CREATE (diMatteo {name: "Roberto Di Matteo"})
CREATE (benitez {name: "Rafael Benitez"})
CREATE (ranieri)-[:SUCCEEDED_BY]->(mourinho)
CREATE (mourinho)-[:SUCCEEDED_BY]->(grant)
CREATE (grant)-[:SUCCEEDED_BY]->(scolari)
CREATE (scolari)-[:SUCCEEDED_BY]->(wilkins)
CREATE (wilkins)-[:SUCCEEDED_BY]->(hiddink)
CREATE (hiddink)-[:SUCCEEDED_BY]->(ancelotti)
CREATE (ancelotti)-[:SUCCEEDED_BY]->(villasBoas)
CREATE (villasBoas)-[:SUCCEEDED_BY]->(diMatteo)
CREATE (diMatteo)-[:SUCCEEDED_BY]->(benitez)
CREATE (benitez)-[:SUCCEEDED_BY]->(mourinho)
Мы хотим написать запрос, который будет возвращать пары ‘SUCCEEDED_BY’, начиная с Клаудио Раньери и заканчивая вниз.
Мы могли бы начать с этого запроса, который начинается с Раньери и идет вниз по дереву в поисках следующего преемника:
START m = node:node_auto_index(name="Claudio Ranieri") MATCH path = (m)-[rel:SUCCEEDED_BY*]->(successor) RETURN EXTRACT(n IN NODES(path): n.name)
==> +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ==> | EXTRACT(n IN NODES(path): n.name) | ==> +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ==> | ["Claudio Ranieri","Jose Mourinho"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins","Guus Hiddink"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins","Guus Hiddink","Carlo Ancelotti"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins","Guus Hiddink","Carlo Ancelotti","Andre Villas Boas"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins","Guus Hiddink","Carlo Ancelotti","Andre Villas Boas","Roberto Di Matteo"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins","Guus Hiddink","Carlo Ancelotti","Andre Villas Boas","Roberto Di Matteo","Rafael Benitez"] | ==> | ["Claudio Ranieri","Jose Mourinho","Avram Grant","Luiz Felipe Scolari","Ray Wilkins","Guus Hiddink","Carlo Ancelotti","Andre Villas Boas","Roberto Di Matteo","Rafael Benitez","Jose Mourinho"] | ==> +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ==> 10 rows
Это дает нам все комбинации, но, к сожалению, включает и всех предыдущих преемников, так что это не совсем то, что мы хотим.
Нам нужно манипулировать запросом таким образом, чтобы у нас был список всех менеджеров, а затем мы могли следовать за одним отношением ‘SUCCEEDED_BY’, чтобы найти их преемника.
Мы могли бы легко получить этот список менеджеров, следуя отношениям «SUCCEEDED_BY» и получая узлы на другой стороне, но это привело бы к исключению Клаудио Раньери, поскольку у него нет входящих отношений.
Чтобы сохранить Ranieri, мы можем использовать путь длины 0 следующим образом:
START m = node:node_auto_index(name="Claudio Ranieri") MATCH path = (m)-[rel:SUCCEEDED_BY*0..]->(mm) RETURN mm
==> +--------------------------------------+
==> | mm |
==> +--------------------------------------+
==> | Node[8]{name:"Claudio Ranieri"} |
==> | Node[9]{name:"Jose Mourinho"} |
==> | Node[10]{name:"Avram Grant"} |
==> | Node[11]{name:"Luiz Felipe Scolari"} |
==> | Node[12]{name:"Ray Wilkins"} |
==> | Node[13]{name:"Guus Hiddink"} |
==> | Node[14]{name:"Carlo Ancelotti"} |
==> | Node[15]{name:"Andre Villas Boas"} |
==> | Node[16]{name:"Roberto Di Matteo"} |
==> | Node[17]{name:"Rafael Benitez"} |
==> | Node[9]{name:"Jose Mourinho"} |
==> +--------------------------------------+
==> 11 rows
Если мы теперь следуем отношениям SUCCEEDED_BY из нашего списка менеджеров, мы получим пары менеджеров:
START m = node:node_auto_index(name="Claudio Ranieri") MATCH path = (m)-[rel:SUCCEEDED_BY*0..]->(mm)-[:SUCCEEDED_BY]->(successor) RETURN DISTINCT mm.name, successor.name
==> +-----------------------------------------------+ ==> | mm.name | successor.name | ==> +-----------------------------------------------+ ==> | "Claudio Ranieri" | "Jose Mourinho" | ==> | "Jose Mourinho" | "Avram Grant" | ==> | "Avram Grant" | "Luiz Felipe Scolari" | ==> | "Luiz Felipe Scolari" | "Ray Wilkins" | ==> | "Ray Wilkins" | "Guus Hiddink" | ==> | "Guus Hiddink" | "Carlo Ancelotti" | ==> | "Carlo Ancelotti" | "Andre Villas Boas" | ==> | "Andre Villas Boas" | "Roberto Di Matteo" | ==> | "Roberto Di Matteo" | "Rafael Benitez" | ==> | "Rafael Benitez" | "Jose Mourinho" | ==> +-----------------------------------------------+ ==> 10 rows
Код для этого доступен на консоли neo4j, если вы заинтересованы в дальнейшей игре с ним.