Język zapytań Cypher - zapisywanie i odczytywanie danych z Neo4j

Cypher to język zapytań grafowych baz danych Neo4j, który umożliwia pobieranie danych, aktualizację danych i administrację grafami. Został zaprojektowany tak, aby był odpowiedni zarówno dla programistów, jak i specjalistów operacyjnych. Cypher jest prosty, ale potężny; bardzo skomplikowane zapytania do bazy danych można łatwo wyrazić, co pozwala skupić się na właściwej pracy, zamiast tracić czas na pisanie skomplikowanego kodu. Cypher pierwotnie miał być używany z grafową bazą danych Neo4j, ale został otwarty w ramach projektu openCypher w październiku 2015 r.

Struktura języka Cypher

Cypher zapożycza swoją strukturę z SQL — zapytania są budowane przy użyciu różnych klauzul. Klauzule są ze sobą połączone i przekazują między sobą pośrednie zestawy wyników. Na przykład pasujące zmienne z jednej klauzuli MATCH będą kontekstem, w którym istnieje następna klauzula. Język zapytań składa się z kilku odrębnych klauzul.

Oto kilka przykładów klauzul używanych do odczytywania z grafu:

  • MATCH: Wzorzec grafu do dopasowania. Jest to najczęstszy sposób uzyskiwania danych z grafu.

  • WHERE: Nie samodzielna klauzula, ale raczej część MATCH, OPTIONAL MATCH i WITH. Dodaje ograniczenia do wzorca lub filtruje wynik pośredni przechodzący przez WITH.

  • RETURN: Określa co zwrócić.

Poniżej znajdziesz przykłady zapytań z użyciem kauzul, zmiennych, funkcji. By je przetestować razem z przechodzeniem przez ten kurs, stwórz prosty graf w Twojej testowej bazie danych:

CREATE (john:Person {name: 'John'})
CREATE (joe:Person {name: 'Joe'})
CREATE (steve:Person {name: 'Steve'})
CREATE (sara:Person {name: 'Sara'})
CREATE (maria:Person {name: 'Maria'})
CREATE (john)-[:FRIEND]->(joe)-[:FRIEND]->(steve)
CREATE (john)-[:FRIEND]->(sara)-[:FRIEND]->(maria)

OK, przechodzimy do pierwszych zapytań. Na przykład, oto zapytanie, które znajduje użytkownika o nazwie „John” i przyjaciół „John'a” (choć nie jego bezpośrednich znajomych), i zwróci zarówno „John'a”, i wszystkich znalezionych jego znajomych znajomych.

MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof)
RETURN john.name, fof.name

A oto i rezultat tego zapytania:

+----------------------+
| john.name | fof.name |
+----------------------+
| "John"    | "Maria"  |
| "John"    | "Steve"  |
+----------------------+
2 rows

Rodzaje zapytań

Zapytania w języku Cypher możemy podzielić na dwie kategorie; zapytania administracyjne, zapytania odczytujące i zapisujące

Zapytania administracyjne

Zapytań administracyjnych nie można łączyć ze zwykłymi zapytaniami do odczytu i zapisu. Każde zapytanie administracyjne spowoduje wykonanie akcji aktualizacji system lub odczyt informacji o stanie z system. Niektóre polecenia administracyjne wprowadzają zmiany w określonej bazie danych i dlatego będą możliwe do uruchomienia tylko po połączeniu ze wskazaną bazą danych. Inne wprowadzają zmiany w stanie całego DBMS i mogą być uruchamiane tylko w specjalnej bazie danych system.

Zapytania odczytujące i zapisujące

Jeśli odczytasz z grafu, a następnie aktualizujesz graf, Twoje zapytanie ma domyślnie dwie części — czytanie to pierwsza część, a pisanie to druga część.

Dana część zapytania Cypher może odczytywać, dopasowywać dane grafu lub dokonywać na nim aktualizacji. Ale nie jedno i drugie jednocześnie.

Jeśli zapytanie wykonuje tylko odczyty, Cypher nie dopasuje się do wzorca, dopóki nie poprosisz o wyniki. W zapytaniu aktualizującym semantyka polega na tym, że wszystkie odczyty zostaną wykonane przed wykonaniem jakiegokolwiek zapisu.

Jedynym wzorcem, w którym części zapytania są niejawne, jest moment, w którym najpierw czytasz, a następnie zapisujesz — przy innej kolejności musisz wyraźnie określić części zapytania. Części są oddzielone za pomocą instrukcji WITH. WITH jest jak horyzont zdarzeń — jest barierą między planem a skończoną realizacją tego planu.

Jeśli chcesz filtrować za pomocą danych zagregowanych, musisz połączyć ze sobą dwie części zapytania odczytującego — pierwsza wykonuje agregację, a druga filtruje wyniki pochodzące z pierwszej.

MATCH (n {name: 'John'})-[:FRIEND]-(friend)
WITH n, count(friend) AS friendsCount
WHERE friendsCount > 2
RETURN n, friendsCount

Używając WITH, określasz, w jaki sposób agregacja ma się odbywać i że agregacja musi zostać zakończona, zanim Cypher będzie mógł rozpocząć filtrowanie.

Oto przykład aktualizacji grafu, zapisywania zagregowanych danych grafu:

MATCH (n {name: 'John'})-[:FRIEND]-(friend)
WITH n, count(friend) AS friendsCount
SET n.friendsCount = friendsCount
RETURN n.friendsCount

Możesz połączyć ze sobą tyle części zapytania, na ile pozwala dostępna pamięć bazy.

Zwracanie danych

Każde zapytanie może zwrócić dane. Jeśli zapytanie tylko odczytuje, musi zwrócić dane. Jeśli zapytanie odczytu nie zwraca żadnych danych, nie ma to żadnego celu i dlatego nie jest prawidłowym zapytaniem Cypher. Zapytania aktualizujące graf nie muszą niczego zwracać, ale mogą.

Po wszystkich częściach zapytania pojawia się ostatnia klauzula RETURN. RETURN nie jest częścią żadnej części zapytania — jest to symbol podsumowania zapytania. Klauzula RETURN ma trzy pod-klauzule, które mogą być jej częścią: SKIP/ LIMIT i ORDER BY.

Jeśli zwracasz węzły lub relacje z zapytania, które właśnie je usunęło — uważaj, trzymasz wskaźnik, który nie jest już ważny.

Dopasowanie ścieżki Cypher

Dopasowywanie ścieżek Cypher wykorzystuje izomorfizm relacji, ta sama relacja nie może zostać zwrócona więcej niż raz w tym samym rekordzie wyniku.

Ta sekcja może wydać Ci się techno-bełkotem, ale nie pomijaj jej bo zrozumienie jak działają ścieżki jest ważne dla zrozumienia jak pisać zapytania. Neo4j Cypher wykorzystuje izomorfizm relacji do dopasowywania ścieżek który jest bardzo skutecznym sposobem zmniejszania rozmiaru zestawu wyników i zapobiegania nieskończonym przejściom.

W Neo4j wszystkie relacje mają kierunek. Jednak w czasie zapytania możesz używać pojęcia relacji nieskierowanych

W przypadku wyrażeń wzorca o zmiennej długości szczególnie ważne jest, aby mieć kontrolę limitów - w innym przypadku można otrzymać nieskończoną liczbę rekordów wyników.

Aby lepiej to zrozumieć, rozważmy kilka alternatywnych opcji:

Homomorfizm

Brak ograniczeń dotyczących dopasowywania ścieżek.

Izomorfizm węzła

Nie można zwrócić tego samego węzła więcej niż raz dla każdego rekordu pasującego do ścieżki.

Izomorfizm relacji

Nie można zwrócić tej samej relacji więcej niż raz dla każdego rekordu pasującego do ścieżki. Cypher wykorzystuje izomorfizm relacji do dopasowywania ścieżek.

1. Homomorfizm

Ograniczenia: Brak ograniczeń dla dopasowania ścieżki.

Przykład 1. Homomorfizm

Graf składa się tylko z dwóch węzłów (a)i (b)połączonych jedną relacją (a:Node)-[r:R]->(b:Node).

Jeśli zapytanie szuka ścieżek o długości n i nie zależy mu na kierunku, zostanie zwrócona ścieżka o długości n powtarzająca się w kółko przez dwa węzły.

Na przykład znajdź wszystkie ścieżki z 5 relacjami i nie przejmuj się kierunkiem relacji:

MATCH p = ()-[*5]-()
RETURN nodes(p)

Spowoduje to zwrócenie dwóch wynikowych rekordów, jeśli użyto homomorfizmu [a,b,a,b,a,b] , a także [b,a,b,a,b,a].

2. Izomorfizm węzłów

Ograniczenia: ten sam węzeł nie może zostać zwrócony więcej niż raz dla każdego rekordu pasującego do ścieżki.

W innym przykładzie z dwoma węzłami, takim jak (a:Node)-[r:R]->(b:Node); tylko ścieżki o długości 1 może być odnaleziona z ograniczeniem izomorfizmu węzłów.

Przykład 2. Izomorfizm węzła

Graf składa się tylko z dwóch węzłów (a) i (b)połączonych jedną relacją (a:Node)-[r:R]->(b:Node).

MATCH p = ()-[*1]-()
RETURN nodes(p)

Spowoduje to zwrócenie dwóch wynikowych rekordów, jeśli użyto izomorfizmu węzłów [a, b] , a także [b, a].

3. Izomorfizm relacji

Ograniczenia: ta sama relacja nie może zostać zwrócona więcej niż raz dla każdego rekordu pasującego do ścieżki.

W innym przykładzie z dwoma węzłami, takim jak (a:Node)-[r:R]->(b:Node); tylko ścieżki o długości 1 można znaleźć z użyciem ograniczenia izomorfizmu relacji.

Przykład 3. Izomorfizm relacji

Graf składa się tylko z dwóch węzłów (a) i (b)połączonych jedną relacją (a:Node)-[r:R]->(b:Node).

MATCH p = ()-[*1]-()
RETURN nodes(p)

Spowoduje to zwrócenie dwóch wynikowych rekordów [a, b] oraz [b, a].

4. Przykład dopasowania ścieżki w Cypher

Cypher wykorzystuje izomorfizm relacji do dopasowywania ścieżek.

Przykład 4. Przyjaciel znajomych

Szukanie znajomych znajomych użytkownika nie powinno zwracać samego użytkownika.

Aby to zademonstrować, stwórzmy kilka węzłów i relacji:

CREATE
  (adam:User {name: 'Adam'}),
  (pernilla:User {name: 'Pernilla'}),
  (david:User {name: 'David'}),
  (adam)-[:FRIEND]->(pernilla),
  (pernilla)-[:FRIEND]->(david)

Teraz poszukajmy znajomych znajomych Adama:

MATCH (user:User {name: 'Adam'})-[r1:FRIEND]-()-[r2:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

W tym zapytaniu Cypher upewnia się, że nie zwraca dopasowań, w których relacje wzorców r1 i r2wskazują na tę samą relację grafu. Jednak nie zawsze jest to pożądane. Jeśli zapytanie powinno zwrócić użytkownika, możliwe jest rozłożenie dopasowania na wiele MATCH klauzul, na przykład:

MATCH (user:User {name: 'Adam'})-[r1:FRIEND]-(friend)
MATCH (friend)-[r2:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

Wartości i typy danych

W Neo4j mamy różne typy danych. Dzielą się one na kilka kategorii.

Typy właściwości

Integer, Float, String, Boolean, Point, Date, Time, LocalTime, DateTime, LocalDateTime, i Duration

Typy strukturalne

Node, Relationship, i Path

Typy złożone

Listy i mapy

Zasady nazewnictwa i zalecenia

Zasady nazewnictwa

  • Znaki alfabetyczne:

    • Nazwy powinny zaczynać się literą alfabetu.

    • Obejmuje to znaki „inne niż angielskie”, takie jak å, ä, ö, üitp.

  • Liczby:

    • Nazwy nie powinny zaczynać się od cyfry.

    • Ilustrować 1first nie wolno, a first1 wolno.

  • Symbolika:

    • Nazwy nie powinny zawierać symboli, z wyjątkiem podkreślenia, jak w my_variable, lub $ jako pierwszego znaku określającego parametr , jak podano w $myParam.

  • Długość:

    • Może być bardzo długi, do 65535( 2^16 - 1) lub 65534 znaków, w zależności od wersji Neo4j.

  • Wielkość liter ma znaczenie:

    • Nazwy są wrażliwe na wielkość liter, a zatem :PERSON, :Personi :person są trzy różne etykiety, a n i N to dwie różne zmienne.

  • Białe znaki:

    • Wiodące i końcowe białe znaki zostaną automatycznie usunięte. Na przykład MATCH ( a ) RETURN ajest równoważne MATCH (a) RETURN a.

 

Znaki inne niż alfabetyczne, w tym cyfry, symbole i znaki odstępu, mogą być używane w nazwach, ale należy je zmienić za pomocą backticków. Na przykład: `^n`, `1first`, `$$n`, i `my variable has spaces`. Nazwy baz danych stanowią wyjątek i mogą zawierać kropki bez konieczności stosowania znaków 'escape'. Na przykład: nazywanie bazy danych foo.bar.baz jest całkowicie poprawne.

2. Zasady określania zakresu i przestrzeni nazw

  • Etykiety węzłów, typy relacji i nazwy właściwości mogą wielokrotnie wykorzystywać nazwy.

    • Następujące zapytanie — with a dla etykiety, typu i nazwy właściwości — jest poprawne: CREATE (a:a {a: 'a'})-[r:a]->(b:a {a: 'a'}).

  • Zmienne dla węzłów i relacji nie mogą ponownie używać nazw w tym samym zakresie zapytania.

    • Następujące zapytanie jest nieprawidłowe, ponieważ węzeł i relacja mają nazwę a: CREATE (a)-[a]->(b).

3. Zalecenia

Oto zalecane konwencje nazewnictwa:

Etykiety węzłów

"Wielbłąd", zaczynając od wielkiej litery

:VehicleOwnerzamiast :vehicle_owneritp.

Typy relacji

Wielkie litery, użycie podkreślenia do oddzielenia słów

:OWNS_VEHICLEzamiast :ownsVehicleitp.

Wyrażenia

1. Wyrażenia w ogóle

Wyrażenie w Cypher może mieć postać:

  • Literał dziesiętny (całkowity lub zmiennoprzecinkowy): 13, -40000,3.14

  • Literał dziesiętny (liczba całkowita lub zmiennoprzecinkowa) w notacji naukowej: 6.022E23.

  • Szesnastkowy literał całkowity (zaczynający się od 0x): 0x13af, 0xFC3A9, -0x66eff.

  • Literał liczby całkowitej ósemkowej (zaczynający się od 0olub 0): 0o1372, 02127, -0o5671.

  • Literał ciągu znaków: 'Hello', "World".

  • Literał logiczny: true, false.

  • Zmienna: n, x, rel, myFancyVariable, `A name with weird stuff in it[]!`.

  • Właściwość: n.prop, x.prop, rel.thisProperty, myFancyVariable.`(weird property name)`.

  • Właściwość dynamiczna: n["prop"], rel[n.city + n.zip], map[coll[0]].

  • Parametr: $param, $0.

  • Lista wyrażeń: ['a', 'b'], [1, 2, 3], ['a', 2, n.property, $param], [].

  • Wywołanie funkcji: length(p), nodes(p).

  • Funkcja agregująca: avg(x.prop), count(*).

  • Wzorzec ścieżki: (a)-[r]->(b), (a)-[r]-(b), (a)--(b), (a)-->()<--(b).

  • Aplikacja operatorska: 1 + 2, 3 < 4.

  • Wyrażenie predykatu to wyrażenie, które zwraca prawdę lub fałsz: a.prop = 'Hello', length(p) > 10, a.name IS NOT NULL.

  • Podzapytanie egzystencjalne to wyrażenie zwracające prawdę lub fałsz: EXISTS { MATCH (n)-[r]→(p) WHERE p.name = 'Sven' }.

  • Wyrażenie regularne: a.name =~ 'Tim.*'.

  • Wyrażenie dopasowujące ciąg znaków z uwzględnieniem wielkości liter: a.surname STARTS WITH 'Sven', a.surname ENDS WITH 'son'lub a.surname CONTAINS 'son'.

  • Wyrażenie CASE

 

2. Literały ciągów znaków

Literały łańcuchowe mogą zawierać następujące sekwencje specjalne:

 

Sekwencja modyfikacji Postać

\t

Tabulator

\b

Backspace

\n

Nowa linia

\r

Zwrot karetki

\f

Kanał formularza

\'

Pojedynczy cytat

\"

Cudzysłów

\\

Ukośnik wsteczny

\uxxxx

Punkt kodowy Unicode UTF-16 (4 cyfry szesnastkowe muszą następować po znaku \u)

\Uxxxxxxxx

Punkt kodowy Unicode UTF-32 (8 cyfr szesnastkowych musi następować po znaku \U)

 

3. CASE wyrażenia

Ogólne wyrażenia warunkowe mogą być wyrażane przy użyciu dobrze znanej CASE konstrukcji. W Cypherze istnieją dwa warianty CASE : forma prosta, która umożliwia porównanie wyrażenia z wieloma wartościami, oraz forma ogólna, która umożliwia wyrażenie wielu instrukcji warunkowych.

Prosta forma CASE: porównywanie wyrażenia z wieloma wartościami

Wyrażenie jest obliczane i porównywane w kolejności z WHEN klauzulami aż do znalezienia dopasowania. Jeśli nie zostanie znalezione żadne dopasowanie, ELSE zwracane jest wyrażenie w klauzuli. Jeśli jednak nie ma ELSE i nie zostanie znalezione dopasowanie, null zostanie zwrócony.

CASE test
  WHEN value THEN result
  [WHEN ...]
  [ELSE default]
END

lub

MATCH (n)
RETURN
CASE n.eyes
  WHEN 'blue'  THEN 1
  WHEN 'brown' THEN 2
  ELSE 3
END AS result

Forma ogólna CASE: pozwalająca na wyrażenie wielu warunków warunkowych

Predykaty są oceniane w kolejności, aż do znalezienia wartości true, i wynik zostanie zwrócony. Jeśli nie zostanie znalezione żadne dopasowanie, w ELSE zwracane jest wyrażenie w klauzuli. Jeśli jednak nie ma ELSE  i nie zostanie znalezione dopasowanie, null zostanie zwrócony.

CASE
  WHEN predicate THEN result
  [WHEN ...]
  [ELSE default]
END

lub

MATCH (n)
RETURN
CASE
  WHEN n.eyes = 'blue' THEN 1
  WHEN n.age < 40      THEN 2
  ELSE 3
END AS result

Rozróżnianie pomiędzy prostym CASE a formami ogólnymi

Ze względu na bliskie podobieństwo składni obu form, czasami może nie być na początku jasne, której formy użyć. Mamy zilustrować ten scenariusz za pomocą następującej kwerendy, w których istnieje oczekiwanie, że age_10_years_ago to -1, czy n.age jest null:

MATCH (n)
RETURN n.name,
CASE n.age
  WHEN n.age IS NULL THEN -1
  ELSE n.age - 10
END AS age_10_years_ago

Ponieważ jednak to zapytanie jest napisane przy użyciu prostego CASE, zamiast age_10_years_ago zwrócić -1 dla węzła o nazwie Daniel, jest to null. Dzieje się tak, ponieważ dokonuje się porównania między n.agei n.age IS NULL. Ponieważ n.age IS NULL jest to wartość logiczna i n.age jest wartością całkowitą, WHEN n.age IS NULL THEN -1 rezultat nigdy nie jest brany. Powoduje to, że ELSE n.age - 10 rezultat jest pobierany, zwracając null.

Poprawione zapytanie, zachowujące się zgodnie z oczekiwaniami, jest podane w następującej CASE ogólnym:

MATCH (n)
RETURN n.name,
CASE
  WHEN n.age IS NULL THEN -1
  ELSE n.age - 10
END AS age_10_years_ago

Widzimy teraz, że age_10_years_ago poprawnie zwraca się -1 do węzła o nazwie Daniel.

Zmienne

Kiedy odwołujesz się do części wzorca lub zapytania, robisz to, nazywając je. Nazwy, które nadajesz różnym częściom, nazywane są zmiennymi.

MATCH (n)-->(b)
RETURN b

W powyższym przykładzie zmienne to n i b.

Zmienne są widoczne tylko w tej samej części zapytania

Zmienne nie są przenoszone do kolejnych zapytań. Jeśli wiele części zapytania jest połączonych razem za pomocą WITH, zmienne muszą być wymienione w klauzuli WITH, aby zostały przeniesione do następnej części.

Operatory

Operatory agregacji

DISTINCT

Operatory właściwości

.do statycznego dostępu []do właściwości, dynamicznego dostępu =do właściwości, +=do zastępowania wszystkich właściwości, do mutowania określonych właściwości

Operatory matematyczne

+, -, *, /, %,^

Operatory porównania

=, <>, <, >, <=, >=, IS NULL,IS NOT NULL

Operatory porównania specyficzne dla łańcucha

STARTS WITH, ENDS WITH,CONTAINS

Operatory logiczne

AND, OR, XOR,NOT

Operatory ciągów

+do łączenia, =~do dopasowywania wyrażenia regularnego

Operatory czasowe

+oraz -dla operacji między czasami trwania a chwilowymi chwilami/czasami trwania *oraz /dla operacji między czasami trwania i liczbami

Operatory map

.dla statycznego dostępu do wartości przez klucz, []dla dynamicznego dostępu do wartości przez klucz

Operatory list

+dla konkatenacji, IN aby sprawdzić istnienie elementu na liście, []dla dynamicznego dostępu do elementu(ów)

Przykład operatora DISTINCT

CREATE
  (a:Person {name: 'Anne', eyeColor: 'blue'}),
  (b:Person {name: 'Bill', eyeColor: 'brown'}),
  (c:Person {name: 'Carol', eyeColor: 'blue'})
WITH [a, b, c] AS ps
UNWIND ps AS p
RETURN DISTINCT p.eyeColor

Klauzule

MATCH

Klauzula MATCH pozwala określić wzorcena podstawie których Neo4j przeszuka bazę danych. Jest to podstawowy sposób pobierania danych do bieżącego zestawu powiązań.

MATCH jest często połączona z klauzulą WHERE, która dodaje ograniczenia lub predykaty do wzorców MATCH, czyniąc je bardziej precyzyjnymi. Predykaty są częścią opisu wzorca i nie powinny być uważane za filtr zastosowany dopiero po wykonaniu dopasowania. Oznacza to, że WHERE zawsze należy łączyć z klauzulą MATCH

MATCH może wystąpić na początku zapytania lub później, prawdopodobnie po WITH. Jeśli jest to pierwsza klauzula, nic nie zostanie jeszcze powiązane, a Neo4j zaprojektuje wyszukiwanie w celu znalezienia wyników pasujących do klauzuli i wszelkich powiązanych predykatów określonych w dowolnej części WHERE. Może to obejmować skanowanie bazy danych, wyszukiwanie węzłów posiadających określoną etykietę lub przeszukiwanie indeksu w celu znalezienia punktów początkowych do dopasowania wzorca. Węzły i relacje znalezione przez to wyszukiwanie są dostępne jako powiązane elementy wzorca i mogą być używane do dopasowywania wzorców ścieżek. Mogą być również użyte w dowolnych dalszych klauzulach MATCH, gdzie Neo4j użyje znanych elementów, a stamtąd znajdzie kolejne nieznane elementy.

Cypher jest deklaratywny, więc zwykle samo zapytanie nie określa algorytmu, który ma zostać użyty do przeprowadzenia wyszukiwania. Neo4j automatycznie wypracuje najlepsze podejście do znajdowania węzłów początkowych i dopasowywania wzorców. Predykaty w częściach WHERE mogą być oceniane przed dopasowaniem do wzorca, podczas dopasowywania wzorca lub po znalezieniu dopasowań. Istnieją jednak przypadki, w których możesz wpłynąć na decyzje podejmowane przez kompilator zapytań.

Przykłady:

MATCH (n)
RETURN n

Zwraca wszystkie węzły w bazie danych.

MATCH (movie:Movie)
RETURN movie.title

Zwraca wszystkie filmy z bazy danych.

MATCH (director {name: 'Oliver Stone'})--(movie)
RETURN movie.title

Zwraca wszystkie filmy wyreżyserowane przez „Olivera Stone'a” .

Optional Match

OPTIONAL MATCH dopasowuje wzorce do bazy danych grafów, tak jak to robi MATCH. Różnica polega na tym, że jeśli nie zostaną znalezione żadne dopasowania, OPTIONAL MATCHu żyje a null dla brakujących części wzorca. OPTIONAL MATCH może być uważany za odpowiednik outer join w SQL.

Albo cały wzór jest dopasowany, albo nic nie jest dopasowane. Pamiętaj, że WHEREjest to część opisu wzorca, a predykaty będą brane pod uwagę podczas wyszukiwania dopasowań, a nie po. Ma to znaczenie zwłaszcza w przypadku klauzul wielokrotnych ( OPTIONAL) MATCH, gdzie kluczowe jest WHEREzestawienie z tym MATCH, do którego należy. Przykład:

MATCH (a:Movie {title: 'Wall Street'})
OPTIONAL MATCH (a)-->(x)
RETURN x

Zwraca null, ponieważ węzeł nie ma relacji wychodzących.

RETURN

W części RETURN zapytania definiujesz, które części wzorca Cię interesują. Mogą to być węzły, relacje lub właściwości.

MATCH (n {name: 'B'})
RETURN n

Ze względu na wydajność, upewnij się że zwracasz świadomie właściwe węzły i/lub właściwości i relacje. Jeśli chcesz zwrócić wszystkie węzły, relacje i ścieżki znalezione w zapytaniu, możesz użyć *symbolu.

MATCH p = (a {name: 'A'})-[r]->(b)
RETURN *

WITH

Używając WITH, możesz manipulować danymi wyjściowymi przed przekazaniem ich do następujących części zapytania. Można dokonać manipulacji kształtem i/lub liczbą wpisów w zestawie wyników.

Jednym z typowych zastosowań WITH jest ograniczenie liczby wpisów przekazywanych do innych klauzul MATCH. Łącząc ORDER BY i LIMIT można uzyskać najlepsze wpisy X według pewnych kryteriów, a następnie wprowadzić dodatkowe dane z wykresu.

WITH może być również używany do wprowadzania nowych zmiennych zawierających wyniki wyrażeń do użycia w następujących częściach zapytania. Dla wygody symbol wieloznaczny * rozszerza się na wszystkie zmienne, które są aktualnie w zakresie i przenosi je do następnej części zapytania.

Innym zastosowaniem jest filtrowanie według zagregowanych wartości. WITH służy do wprowadzania agregatów, które następnie mogą być używane w predykatach w WHERE. Te wyrażenia agregujące tworzą nowe powiązania w wynikach.

WITH służy również do oddzielenia odczytu od aktualizacji wykresu. Każda część zapytania musi być tylko do odczytu lub tylko do zapisu. Przechodząc z części do pisania do części do czytania, przełączenia należy dokonać za pomocą WITH klauzuli. Przykład:

MATCH (george {name: 'George'})<--(otherPerson)
WITH otherPerson, toUpper(otherPerson.name) AS upperCaseName
WHERE upperCaseName STARTS WITH 'C'
RETURN otherPerson.name

Możesz użyć symbolu wieloznacznego, *aby przenieść wszystkie zmienne, które znajdują się w zakresie, oprócz wprowadzania nowych zmiennych:

MATCH (person)-[r]->(otherPerson)
WITH *, type(r) AS connectionType
RETURN person.name, otherPerson.name, connectionType

Unwind

Za pomocą programu UNWIND możesz przekształcić dowolną listę z powrotem w pojedyncze wiersze. Te listy mogą być parametrami, które zostały przekazane, poprzednio collect-ed wynikiem lub innymi wyrażeniami listowymi.

Jednym z typowych zastosowań unwind jest tworzenie odrębnych list. Innym jest tworzenie danych z list parametrów dostarczonych do zapytania.

UNWIND wymaga podania nowej nazwy dla wartości wewnętrznych.

WHERE

WHERE nie jest klauzulą ​​samą w sobie — jest raczej częścią MATCH, OPTIONAL MATCH i WITH.

W przypadku WITH, WHERE po prostu filtruje wyniki.

Dla MATCH a OPTIONAL MATCH z drugiej strony, WHERE dodaje ograniczenia do zdefiniowanych wzorców. Nie powinno być  WHEREpostrzegane jako filtr po zakończeniu dopasowywania.

ORDER BY

Pamiętaj, że nie możesz sortować według węzłów lub relacji, tylko według ich właściwości. ORDER BY opiera się na porównaniach do sortowania danych wyjściowych.

Jeśli chodzi o zakres zmiennych, ORDER BY obowiązują specjalne zasady, w zależności od tego, czy projekcja RETURNl ub klauzula WITH jest agregacją, czy DISTINCT. Jeśli jest to agregacja lub DISTINCT projekcja, dostępne są tylko zmienne dostępne w projekcji. Jeśli projekcja nie zmienia kardynalności wyjścia (która agregacja i DISTINCT robi), dostępne są również zmienne dostępne przed klauzulą ​​projekcji. Gdy klauzula projekcji przepisuje już istniejące zmienne, dostępne są tylko nowe zmienne.

Wreszcie, nie wolno używać wyrażeń agregujących w ORDER BY klauzuli podrzędnej, jeśli nie są one również wymienione w klauzuli projekcji. Ta ostatnia zasada ma na celu upewnienie się, że ORDER BY nie zmienia wyników, a jedynie ich kolejność.

Na wydajność zapytań Cypher używających ORDER BY właściwości węzła może mieć wpływ istnienie i użycie indeksu do znajdowania węzłów. Jeśli indeks może dostarczyć węzły w kolejności żądanej w zapytaniu, Cypher może uniknąć użycia kosztownej operacji Sort.

Ten tutorial bazuje na oficjalnej dokumentacji Cypher Neo4j - więcej znajdziesz na stronie.