В документах 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, если вы заинтересованы в дальнейшей игре с ним.