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
iWITH
. Dodaje ograniczenia do wzorca lub filtruje wynik pośredni przechodzący przezWITH
. -
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.
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.
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.
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.
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 r2
wskazują 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, afirst1
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
) lub65534
znaków, w zależności od wersji Neo4j.
-
-
Wielkość liter ma znaczenie:
-
Nazwy są wrażliwe na wielkość liter, a zatem
:PERSON
,:Person
i:person
są trzy różne etykiety, an
iN
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 a
jest równoważneMATCH (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 |
|
Typy relacji |
Wielkie litery, użycie podkreślenia do oddzielenia słów |
|
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
0o
lub0
):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'
luba.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ć |
---|---|
|
Tabulator |
|
Backspace |
|
Nowa linia |
|
Zwrot karetki |
|
Kanał formularza |
|
Pojedynczy cytat |
|
Cudzysłów |
|
Ukośnik wsteczny |
|
Punkt kodowy Unicode UTF-16 (4 cyfry szesnastkowe muszą następować po znaku |
|
Punkt kodowy Unicode UTF-32 (8 cyfr szesnastkowych musi następować po znaku |
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.age
i 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 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 MATCH
u ż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 WHERE
jest 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 WHERE
zestawienie 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 RETURN
l 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.