Neo4j, graf, Cypher i wersjonowanie kalendarzowe
Neo4j przechowuje dane jako węzły połączone relacjami, gdzie relacja jest bytem pierwszej kategorii, z własnym typem i własnymi właściwościami. Zapytania pisze się w języku Cypher, który opisuje wzorce w grafie, a nie łączenia tabel.
Zanim sięgniesz po dokumentację, dwie rzeczy zmieniły się na tyle, że starsze materiały wprowadzają w błąd: sposób numerowania wersji oraz to, że język zapytań ma teraz własną wersję, niezależną od bazy.
Wersje kalendarzowe, czyli koniec numerów
Po wydaniu piątki z długim wsparciem projekt przeszedł na wersjonowanie oparte na dacie. Wersja nazywa się teraz według roku, miesiąca i numeru poprawki, na przykład wydanie z czerwca 2026 roku.
Praktyczna konsekwencja jest jedna i warto ją zapamiętać: nie ma czegoś takiego jak Neo4j 6. Materiały mówiące o przejściu na szóstkę są nieporozumieniem albo pochodzą sprzed zmiany. Jeśli szukasz najnowszej wersji, szukasz daty, nie liczby.
Druga konsekwencja dotyczy planowania aktualizacji. Wydania pojawiają się co miesiąc, więc pytanie „czy jesteśmy na bieżącej wersji" ma inną wagę niż przy projekcie wydającym raz na rok. Warto ustalić, czy nadążacie za każdym wydaniem, czy trzymacie się linii z długim wsparciem, i wpisać to do procesu utrzymania.
Trzecia dotyczy czytania dokumentacji. Strony opisujące zmiany są teraz zorganizowane według serii rocznych, więc szukając zachowania konkretnej funkcji trzeba wiedzieć, w której serii pracujesz.
Cypher z własną wersją i standard GQL
To jest zmiana rzadko spotykana w bazach danych i warto zrozumieć, po co ją wprowadzono.
Język zapytań ma teraz własne wersjonowanie, niezależne od bazy. Wersja piąta języka to ta znana z dotychczasowych wydań, a dwudziesta piąta to nowsza, nazwana od roku wprowadzenia.
Zysk polega na tym, że aktualizacja bazy nie wymusza zmiany zapytań. Możesz podnieść wersję serwera, zostawiając zapytania w starszej wersji języka, i przejść na nowszą osobno, wtedy gdy Ci pasuje. To rozwiązuje problem, który przy bazach bywa najbardziej bolesny: aktualizacja wymagająca jednoczesnej zmiany kodu w kilkudziesięciu miejscach.
Drugi wątek to zbieżność ze standardem GQL, czyli międzynarodową normą dla języków zapytań grafowych. Cypher był jej głównym punktem odniesienia, a nowsza wersja języka przybliża się do niej także w składni, na przykład dodając konstrukcję iterującą znaną ze standardu obok dotychczasowej.
Dla użytkownika ma to znaczenie przy ocenie ryzyka związania z dostawcą. Język opisany normą jest łatwiejszy do przeniesienia niż język będący własnością jednej firmy, choć w praktyce różnice między implementacjami pozostają na tyle duże, że migracja nie jest bezbolesna.
Kiedy graf wygrywa z tabelami
Warto to rozstrzygnąć konkretnie, bo baza grafowa bywa wybierana z fascynacji, a nie z potrzeby.
Graf wygrywa tam, gdzie pytanie dotyczy ścieżki, a nie wiersza. „Jak ta osoba jest powiązana z tamtą", „przez ile pośredników przechodzą te pieniądze", „co rekomendować komuś na podstawie tego, co kupili ludzie podobni do niego". W bazie relacyjnej każde z tych pytań to łączenie tabeli ze sobą kilka razy, a koszt rośnie wykładniczo z liczbą poziomów.
Graf wygrywa też przy strukturze, która zmienia kształt. Dodanie nowego rodzaju powiązania między istniejącymi bytami to dopisanie relacji, a nie migracja schematu.
Graf przegrywa przy zapytaniach obejmujących wszystko: sumach, średnich, raportach za okres. Tam baza relacyjna z odpowiednim indeksem jest szybsza i prostsza.
Przegrywa też przy danych, które są w istocie tabelaryczne. Lista zamówień z pozycjami to relacja jeden do wielu, a nie graf, i modelowanie jej jako grafu dokłada złożoność bez zysku.
Praktyczny test brzmi: jeśli Twoje pytania mają w sobie „przez", „pośrednio" albo „ile kroków", graf ma sens. Jeśli mają „ile" i „za okres", zostań przy PostgreSQL.
Cypher w praktyce
MATCH (osoba:Osoba {email: $email})-[:PRACUJE_W]->(firma:Firma)
<-[:PRACUJE_W]-(wspolpracownik:Osoba)
WHERE wspolpracownik <> osoba
RETURN wspolpracownik.imie, firma.nazwa
LIMIT 20Składnia opisuje wzorzec rysunkiem: nawiasy okrągłe to węzły, strzałki to relacje, a kierunek strzałki ma znaczenie. To jest największa zaleta tego języka, bo zapytanie da się przeczytać jako zdanie o strukturze.
Trzy rzeczy warto wiedzieć od początku.
Kierunek relacji przy wyszukiwaniu można pominąć, pisząc bez strzałki, i przy relacjach symetrycznych zwykle tak trzeba. Zostawienie kierunku tam, gdzie dane zapisano w drugą stronę, daje pusty wynik bez żadnego błędu.
Ograniczenie długości ścieżki jest obowiązkowe przy przeszukiwaniu w głąb. Zapytanie szukające połączeń bez ograniczenia liczby kroków potrafi przejść przez cały graf i nie wrócić, a przy dużym zbiorze zablokować serwer.
Etykiety węzłów i typy relacji warto nadawać konsekwentnie, bo to one pozwalają planiście zawęzić obszar. Zapytanie bez etykiety zaczyna od wszystkich węzłów w bazie.
Edycje i co jest w której
Podział na edycję społecznościową i komercyjną jest tu najważniejszą decyzją operacyjną i warto go znać przed rozpoczęciem.
Edycja społecznościowa jest darmowa i wystarcza do nauki, prototypów oraz mniejszych wdrożeń na jednej maszynie. Dostajesz pełny język zapytań, sterowniki i narzędzia.
Czego w niej nie ma: klastrowania, czyli działania na wielu serwerach, kontroli dostępu opartej na rolach, kopii zapasowych wykonywanych bez zatrzymania bazy oraz części możliwości administracyjnych.
Praktyczne skutki są dwa. Brak klastrowania znaczy, że dostępność opiera się na jednej maszynie, więc jej awaria to przestój. Brak kopii bez zatrzymania znaczy, że wykonanie kopii wymaga okna serwisowego, co przy bazie pracującej całą dobę jest problemem.
Dla wdrożenia produkcyjnego z wymogiem ciągłości to zwykle przesądza sprawę na rzecz edycji komercyjnej albo wariantu zarządzanego w chmurze. Dla narzędzia wewnętrznego, analizy albo prototypu edycja darmowa jest w porządku i warto z niej korzystać bez poczucia, że to wersja okrojona do bezużyteczności.
Modelowanie, czyli decyzje podejmowane na starcie
Model grafu wygląda na swobodny i właśnie dlatego łatwo w nim o decyzje, które mszczą się po roku.
Pierwsza dotyczy tego, co jest węzłem, a co właściwością. Miasto zapisane jako właściwość osoby jest łańcuchem znaków, po którym da się filtrować i nic więcej. Miasto jako osobny węzeł pozwala pytać, kto jeszcze tam mieszka i co się z tym miastem wiąże. Reguła praktyczna: jeśli będziesz pytał o powiązania czegoś, to jest węzeł, a jeśli tylko o wartość, to właściwość.
Druga dotyczy kierunku relacji. W grafie relacja zawsze ma kierunek, nawet gdy pojęcie jest symetryczne, więc znajomość między dwiema osobami trzeba zapisać w jedną stronę i pamiętać, żeby przy wyszukiwaniu kierunku nie narzucać. Zapisywanie obu kierunków podwaja dane i tworzy okazję do rozjazdu.
Trzecia dotyczy właściwości na relacjach. Data nawiązania współpracy albo waga powiązania należą do relacji, a nie do żadnego z węzłów, i to jest jedna z rzeczy, których model relacyjny nie wyraża wprost. Wykorzystanie tego odróżnia dobry model grafu od tabeli przepisanej na węzły.
Czwarta dotyczy węzłów o bardzo wielu połączeniach. Węzeł reprezentujący popularną kategorię albo kraj potrafi mieć miliony relacji, a każde zapytanie przez niego przechodzące musi je przejrzeć. Rozwiązaniem bywa rozbicie takiego węzła na kilka według dodatkowego kryterium albo ominięcie go w zapytaniu.
Utrzymanie i wydajność
Kilka rzeczy operacyjnych, które w tej bazie działają inaczej niż w relacyjnej.
Indeksy zakładasz na właściwościach węzłów o określonej etykiecie i służą do jednego: znalezienia punktu startowego. Samo przechodzenie po relacjach indeksu nie potrzebuje, bo relacja jest fizycznym wskaźnikiem. To dlatego wydajność zapytania grafowego zależy głównie od tego, jak szybko trafisz do pierwszego węzła.
Ograniczenia unikalności pełnią podwójną rolę: pilnują danych i przy okazji tworzą indeks. Warto je zakładać na identyfikatorach naturalnych, bo bez nich powielone węzły powstają cicho przy wielokrotnym ładowaniu tych samych danych.
Ładowanie dużych zbiorów wymaga rozbicia na porcje. Pojedyncza transakcja wstawiająca milion węzłów zużyje pamięć i przewróci się, a rozbicie na paczki po kilka tysięcy działa przewidywalnie.
Plan wykonania zapytania da się obejrzeć i warto to robić przy każdym zapytaniu, które ma trafić na produkcję. Pokazuje, od którego węzła zaczyna wyszukiwanie i ile elementów przechodzi na każdym kroku, a to zwykle wyjaśnia różnicę między zapytaniem trwającym milisekundy a takim, które nie wraca.
Neo4j kontra alternatywy
| Rozwiązanie | Model | Licencja | Kiedy wybrać |
|---|---|---|---|
| Neo4j | Graf natywny, Cypher | Społecznościowa lub komercyjna | Pytania o ścieżki i powiązania |
| PostgreSQL z rekurencją | Tabele plus zapytania rekurencyjne | Otwarta | Graf jest dodatkiem, nie sednem |
| Bazy grafowe osadzone | Graf w procesie aplikacji | Zwykle otwarta | Mały graf, brak osobnej usługi |
| Zep z Graphiti | Graf z osią czasu na tej bazie | Otwarta biblioteka | Pamięć agenta, nie ogólny graf |
Drugi wiersz warto rozważyć uczciwie, zanim dołożysz kolejną bazę do stosu. Zapytania rekurencyjne w bazie relacyjnej obsługują przeszukiwanie hierarchii i niezbyt głębokie ścieżki, a przy strukturze drzewiastej bywają wystarczające. Zysk polega na tym, że nie stawiasz drugiej bazy, nie synchronizujesz jej i nie utrzymujesz.
Granica przebiega przy głębokości i przy liczbie typów powiązań. Trzy poziomy w jednym rodzaju relacji obsłuży baza relacyjna. Sześć poziomów przez cztery różne typy relacji jest miejscem, w którym graf zaczyna wygrywać wyraźnie.
Ostatni wiersz jest przypomnieniem, że ta baza bywa fundamentem innych narzędzi. Warstwa pamięci agenta oparta o graf z osią czasu może działać właśnie na niej, co przy wyborze rozwiązania do pamięci warto wiedzieć, bo oznacza jedną bazę do utrzymania więcej.
Wyszukiwanie wektorowe i grafy wiedzy
Baza obsługuje typ wektorowy i indeks pozwalający szukać po podobieństwie, co ma konkretne zastosowanie przy aplikacjach opartych o modele językowe.
Sedno pomysłu polega na połączeniu dwóch sposobów wyszukiwania. Podobieństwo semantyczne znajduje fragmenty pasujące do pytania, a przejście po relacjach dokłada kontekst, którego w samym fragmencie nie było: kto jest autorem, do jakiego projektu należy dokument, co jeszcze z niego wynika.
To jest przewaga nad zwykłym magazynem wektorów, gdzie fragmenty są od siebie niezależne i model dostaje pięć akapitów bez informacji o tym, jak się mają do siebie.
Cena jest taka, że graf trzeba zbudować, a to wymaga wyciągnięcia bytów i relacji z tekstu, zwykle przy pomocy modelu. Koszt tego kroku rośnie z liczbą dokumentów i bywa większy niż koszt samego wyszukiwania.
Najbardziej znaną realizacją tego pomysłu jest GraphRAG, gdzie graf encji dzieli się na skupiska, a model streszcza każde z nich, żeby odpowiadać na pytania o cały zbiór, a nie o pojedynczy fragment. Rachunek za samo indeksowanie idzie tam w setki dolarów przy tysiącu dokumentów i wraca przy każdej większej zmianie w zbiorze, więc w praktyce sięga się po warianty odkładające streszczanie do momentu zapytania.
Praktyczna rada: to podejście opłaca się przy dokumentach, między którymi faktycznie istnieją powiązania warte wyszukiwania. Przy zbiorze niezależnych artykułów pomocy zwykły magazyn wektorów albo rozszerzenie do bazy relacyjnej wystarcza i kosztuje mniej.
Typowe błędy
Pierwszy to szukanie wersji Neo4j 6. Po piątce z długim wsparciem numerowanie przeszło na wersje kalendarzowe, więc szuka się daty, nie liczby.
Drugi to zapytanie przeszukujące ścieżki bez ograniczenia liczby kroków. Przy dużym grafie potrafi przejść przez wszystko i zablokować serwer.
Trzeci to kierunek relacji zostawiony tam, gdzie dane zapisano odwrotnie. Wynik jest pusty, a błędu nie ma, więc szuka się przyczyny w danych zamiast w zapytaniu.
Czwarty to modelowanie jako grafu danych, które są tabelaryczne. Lista zamówień z pozycjami to relacja jeden do wielu i graf nie daje tu nic poza dodatkową bazą do utrzymania.
Piąty to wdrożenie edycji społecznościowej tam, gdzie wymagana jest ciągłość działania. Brak klastrowania i kopii bez zatrzymania oznacza przestój przy awarii i przy tworzeniu kopii.
Szósty to pomijanie etykiet węzłów w zapytaniach. Bez nich planista zaczyna od wszystkich węzłów w bazie, a zapytanie, które działało na tysiącu węzłów, przestaje działać na milionie.
FAQ
Jaka jest najnowsza wersja Neo4j?
Wersje są od 2025 roku kalendarzowe, w formacie rok, miesiąc i numer poprawki, więc najnowsza to najświeższa data, a nie najwyższa liczba. Nie istnieje Neo4j 6, a materiały mówiące o przejściu na szóstkę pochodzą sprzed tej zmiany.
Czym jest Cypher 25?
Wersją języka zapytań, nazwaną od roku wprowadzenia i wersjonowaną niezależnie od bazy. Dzięki temu podniesienie wersji serwera nie wymusza jednoczesnej zmiany wszystkich zapytań, bo starszą wersję języka można zostawić i przejść na nowszą osobno.
Czy edycja społecznościowa wystarczy na produkcję?
Do wdrożeń na jednej maszynie bez wymogu ciągłości tak. Nie ma w niej klastrowania, kontroli dostępu opartej na rolach ani kopii zapasowych bez zatrzymania bazy, więc przy wymogu dostępności i regularnych kopii potrzebna jest edycja komercyjna albo wariant zarządzany.
Kiedy graf jest lepszy od bazy relacyjnej?
Gdy pytania dotyczą ścieżek i powiązań przez wiele poziomów, a nie sum i średnich. Test praktyczny: jeśli w pytaniach pojawia się „przez", „pośrednio" albo „ile kroków", graf ma sens. Przy raportach za okres PostgreSQL jest szybszy i prostszy.
Czy to zastąpi bazę wektorową?
Przy grafach wiedzy, gdzie oprócz podobieństwa liczą się powiązania między fragmentami, daje więcej niż zwykły magazyn wektorów. Przy zbiorze niezależnych dokumentów bez istotnych relacji jest to nadmiar, a koszt budowy grafu przewyższa zysk.
Dokumentacja stoi na stronie projektu, a opis zmian w serii bieżącej w podręczniku operacyjnym.