- Neomodel to Pythonic OGM dla Neo4j, oferujący modele oparte na klasach, wymuszanie schematu i bogate API zapytań na bazie oficjalnego sterownika.
- Aktualne wersje są zgodne z SemVer, obsługują nowoczesne wersje Pythona i Neo4j oraz wprowadzają bardziej rygorystyczne kontrole kardynalności, lepszą konfigurację i kontrolę scalania partii.
- Biblioteka zapewnia zarówno interfejsy API synchronizacji, jak i asynchroniczności, narzędzia do automatycznego tworzenia schematów, integrację z Django oraz elastyczną możliwość przejścia do surowego kodu Cypher w przypadku złożonych zapytań.
- Rozwiązanie neomodel, będące obecnie częścią Neo4j Labs, korzysta z aktywnej konserwacji, testów integracyjnych i rzeczywistych informacji zwrotnych pochodzących z wdrożeń korporacyjnych.

Neomodel to narzędzie do mapowania grafów obiektów (OGM) w języku Python zaprojektowane tak, aby praca z Neo4j była tak naturalna, jak pisanie zwykłego kodu w języku Python. Zamiast ręcznego tworzenia zapytań Cypher, opisujesz swoją domenę grafu klasami, polami i relacjami, a neomodel zajmuje się mapowaniem między obiektami Pythona a węzłami i relacjami Neo4j. Jest on zbudowany na bazie oficjalnego sterownika Neo4j dla Pythona, z jedynie cienką warstwą abstrakcji, dzięki czemu zapewnia wygodę wysokiego poziomu bez znaczącego spadku wydajności.
Jako część ekosystemu Neo4j Labs, neomodel jest aktywnie utrzymywany, w pełni obsługuje nowoczesne wersje Pythona i Neo4j oraz oferuje zarówno synchroniczne, jak i asynchroniczne interfejsy API. Zawiera znane definicje modeli podobne do Django, bogate API zapytań, wymuszanie schematu za pomocą kardynalności, wbudowane transakcje i ścisłą integrację z Django poprzez django_neomodelJednocześnie pozostaje on bardzo szybki: zawsze możesz powrócić do surowego Cyphera, gdy wydajność lub złożoność zapytania tego wymagają.
Czym jest neomodel i dlaczego jest ważny
Neomodel to mapowanie grafów obiektów dla bazy danych grafów Neo4j, łączące klasy Pythona i struktury grafów. Zamiast ręcznie tworzyć węzły i relacje za pomocą ciągów Cypher, definiujesz klasy Pythona, które reprezentują encje domeny, a Neomodel przekształca je w oznaczone węzły z indeksowanymi właściwościami i ograniczeniami w Neo4j. Bazuje on na oficjalnym neo4j-python-driver, więc jego zachowanie jest zgodne z tym, co zrobiłbyś używając bezpośrednio sterownika.
Biblioteka kładzie nacisk na znany styl modelowania oparty na klasach z solidnym dziedziczeniem, hakami i walidacją. To podejście jest szczególnie wygodne dla programistów przyzwyczajonych do Django ORM lub innych ORM-ów w Pythonie: atrybuty klas modelu odpowiadają właściwościom w Neo4j, a specjalne pola relacji przechwytują krawędzie grafu. Dzięki temu rozwiązaniu przeglądanie grafu sprowadza się do śledzenia atrybutów obiektów, zamiast ciągłego pisania rozwlekłego kodu Cypher.
W tle neomodel oferuje potężne API zapytań, które obejmuje powszechnie stosowane wzorce dostępu do grafu, bez konieczności natychmiastowego korzystania z surowego Cyphera. Możesz filtrować, porządkować, przeglądać relacje, wycinać zestawy węzłów i wykonywać zaawansowane operacje za pomocą interfejsu Pythona. W razie potrzeby nadal masz dostęp do… cypher_query pomocnik umożliwiający wykonywanie niestandardowych zapytań i bezpośrednią pracę z zwróconymi wynikami.
Kolejną ważną cechą jest egzekwowanie schematu za pomocą reguł kardynalności w relacjach i ograniczeniach właściwości. Określając kardynalność (na przykład zero lub więcej, jeden lub więcej lub jeden) bezpośrednio w polach relacji, możesz wymusić strukturalne oczekiwania w swoim grafie i pozwolić neomodelowi uniknąć niespójności danych. Indeksy i ograniczenia są tworzone automatycznie na podstawie definicji modelu, a dostępne są narzędzia CLI do ich kontrolowanego stosowania lub usuwania z bazy danych.
Neomodel w pełni obsługuje pracę transakcyjną i można go bezpiecznie stosować w środowiskach wielowątkowych. Transakcje można otwierać i zatwierdzać w przewidywalny sposób, a ponieważ warstwa otaczająca oficjalny sterownik jest celowo cienka, obciążenie wydajnościowe jest niewielkie. Testy porównawcze z narzędziami takimi jak Locust pokazują, że warstwa abstrakcji neomodelu generuje minimalne opóźnienia, nawet przy jednoczesnym obciążeniu.
Obsługa wersji, SemVer i konfiguracja
Nowoczesne wydania neomodelowe są zgodne z wersjonowaniem semantycznym (SemVer) przy użyciu klasycznego wzorca major.minor.patch. Oznacza to, że zmiany powodujące przerwy w działaniu systemu są wprowadzane tylko wraz z aktualizacjami wersji głównych, nowe funkcje bez zakłóceń w działaniu systemu są udostępniane jako drobne wydania, a poprawki błędów są udostępniane jako wersje poprawek. Taka strategia wersjonowania ułatwia planowanie aktualizacji, szczególnie w systemach produkcyjnych.
W serii 6.x neomodel opiera się na aktualnych wersjach Pythona i Neo4j, aby odpowiadać tym, na których działa większość poważnych wdrożeń. Dokładniej, neomodel 6.x wymaga Pythona 3.10 lub nowszego i obsługuje Neo4j 5.x, Neo4j 4.4 LTS oraz nowszą linię Neo4j 2025.xx. Obsługiwane są Neo4j Community, Neo4j Enterprise i Neo4j Aura (usługa hostowana), co daje elastyczność w zakresie sposobu i miejsca hostowania bazy danych.
W przypadku starszych środowisk wcześniejsze gałęzie neomodel nadal obejmują starsze kombinacje Pythona i Neo4j. Linia 5.x obsługuje Pythona 3.8+ z Neo4j 5.x i 4.4 (LTS), natomiast linia 4.x obejmuje Pythona od 3.7 do 3.10 oraz Neo4j 4.x, w tym 4.4 LTS przy użyciu Neomodel 4.0.10. Ta historia zgodności umożliwia stopniową migrację do nowszych wersji przy jednoczesnym zachowaniu działania istniejących konfiguracji.
Począwszy od neomodelu 6 konfiguracja jest obsługiwana za pośrednictwem nowoczesnej klasy danych z adnotacjami typu, walidacją w czasie wykonywania i obsługą zmiennych środowiskowych. Zamiast rozproszonych ustawień ad-hoc, pola konfiguracji są weryfikowane podczas aktualizacji, w tym pod kątem kontroli typów i ograniczeń logicznych. Zmienne środowiskowe można wykorzystać do łatwego nadpisywania konfiguracji, co dobrze sprawdza się w przypadku wdrożeń kontenerowych i środowisk chmurowych.
Wersja 6.0 wprowadza również wyraźne zmiany zakłócające działanie interfejsu i poprawki zachowania, dzięki którym API staje się bardziej przewidywalne. Na przykład rozdzielczość listy z Cypher zwraca teraz oczekiwaną głębokość: zapytanie takie jak RETURN collect(node) będzie mapować do results[0][0] zamiast poprzedniego, nieintuicyjnego results[0][0][0] struktura. Kontrola kardynalności jest bardziej rygorystyczna i domyślnie włączona, a kilka samodzielnych funkcji pomocniczych zostało przeniesionych do centralnej Database() oraz AsyncDatabase() klasy singleton.
Instalacja i konfiguracja
Zalecanym sposobem instalacji neomodel jest instalacja bezpośrednio z PyPI przy użyciu preferowanego menedżera pakietów. Możesz dodać go do środowiska wirtualnego za pomocą prostego polecenia instalacyjnego, a następnie zarządzać aktualizacjami za pomocą standardowych narzędzi do zarządzania zależnościami. Jeśli potrzebujesz najnowszych zmian lub chcesz się do nich przyczynić, możesz również zainstalować go bezpośrednio z repozytorium GitHub.
Przed uruchomieniem jakiegokolwiek kodu neomodel musisz skonfigurować adres URL połączenia, aby biblioteka wiedziała, jak połączyć się z Twoją instancją Neo4j. Ta konfiguracja zazwyczaj obejmuje schemat (Bolt lub Neo4j), hosta, port, nazwę użytkownika, hasło i opcjonalną nazwę bazy danych. W przypadku projektów Django ta konfiguracja jest zazwyczaj umieszczana w settings.py więc jest on inicjowany zaraz po uruchomieniu aplikacji.
Jeśli serwer Neo4j został niedawno zainstalowany, należy zmienić domyślne hasło za pomocą przeglądarki Neo4j lub panelu administracyjnego. Domyślnie ten panel jest dostępny pod adresem http://localhost:7474. Po zaktualizowaniu hasła i potwierdzeniu dbms.security.auth_enabled=true w konfiguracji bazy danych jesteś gotowy na połączenie z neomodel.
Do celów programistycznych i testowych zazwyczaj używa się oddzielnych baz danych Neo4j i dedykowanych poświadczeń. Własny zestaw testów Neomodel wymaga bazy danych Neo4j 4+ i wymaga określonych zmiennych środowiskowych do połączenia. Jeśli uruchomisz testy na zupełnie nowej bazie danych, zestaw testów ustawi hasło na test domyślnie; jeśli wykryje istniejący zestaw danych, odmówi kontynuowania, chyba że jawnie przekażesz flagę resetowania, co pomoże uniknąć przypadkowej utraty danych.
Jeśli chcesz przetestować neomodel w wielu wersjach Pythona i Neo4j, Docker i docker-compose mogą automatycznie zorganizować wszystko. Projekt zapewnia konfigurację umożliwiającą utworzenie macierzy wersji interpretera i wydań Neo4j, co pozwala na spójne przeprowadzanie testów integracyjnych. Jest to szczególnie przydatne, jeśli wprowadzasz funkcje, które powinny działać w kilku obsługiwanych wersjach.
Główne cechy: modele, schemat i indeksy
Sercem Neomodelu są definicje modeli oparte na klasach, które są bezpośrednio odwzorowywane na etykiety węzłów i relacje Neo4j. Zwykle klasy węzłów są tworzone na podstawie StructuredNodei zajęcia z relacji z StructuredRelPola węzłów są definiowane przy użyciu typów właściwości specyficznych dla neomodelu, które kontrolują sposób przechowywania i walidacji danych w Neo4j.
Każda klasa modelu staje się etykietą w Neo4j, a neomodel automatycznie zarządza indeksami i ograniczeniami na podstawie definicji. Oznacza to, że unikalność, wymagane właściwości i pola indeksowane można określić w Pythonie bez konieczności ręcznego tworzenia poleceń Cypher do tworzenia schematu. W tle, Neomodel tłumaczy metadane modelu na odpowiednie operacje schematu Neo4j.
Relacje są przypisane do klas węzłów za pomocą specjalnych deskryptorów, takich jak RelationshipTo, RelationshipFrom, Relationship. Te deskryptory definiują typ relacji, kardynalność i kierunek przechodzenia. RelationshipTo oraz RelationshipFrom wyrazić nawigację jednokierunkową z punktu widzenia Pythona, podczas gdy Relationship używa się, gdy chcemy traktować relację jako nawigowalną w obu kierunkach z poziomu kodu, mimo że sam Neo4j zawsze przechowuje relacje z kierunkiem.
W przypadku relacji logicznie dwukierunkowych zalecaną praktyką jest unikanie tworzenia dwóch pól lustrzanych i używanie jednego Relationship zamiast. Dzięki temu model pozostaje przejrzysty i spójny, a jednocześnie umożliwia przechodzenie w obu kierunkach w kodzie Pythona. Neo4j nadal będzie przechowywać relację skierowaną „pod maską”, ale abstrakcja neomodelu ukrywa ten szczegół podczas przechodzenia.
W przypadku scenariuszy, w których struktury węzłów nie są w pełni znane z góry, neomodel oferuje SemiStructuredNode klasa bazowa. Klasy pochodne tego typu mogą zawierać właściwości „ad hoc”, które nie zostały jawnie zdefiniowane w modelu. Jest to szczególnie przydatne, gdy schemat grafu często ewoluuje lub gdy trzeba sporadycznie dołączyć dodatkowe atrybuty bez konieczności refaktoryzacji modelu za każdym razem.
Reguły kardynalności wymuszają liczbę dozwolonych relacji między węzłami i są obecnie wspierane przez bardziej rygorystyczne kontrole w neomodelu 6. Miękkie sprawdzanie kardynalności jest dostępne dla wszystkich kardynalności relacji, a ścisłe sprawdzanie jest domyślnie włączone. Jeśli Twoje dane naruszają skonfigurowane reguły relacji, neomodel zgłosi ten problem, zamiast po cichu dopuszczać do utrzymywania się niespójnej struktury.
Automatyczne zarządzanie schematami i ich kontrola
Po zdefiniowaniu lub zaktualizowaniu modeli należy zastosować odpowiednie ograniczenia i indeksy do bazy danych Neo4j. Neomodel jest dostarczany ze skryptem o nazwie neomodel_install_labels który skanuje Twoje modele i tworzy lub aktualizuje wymagane indeksy i ograniczenia. Po zmianie schematu należy uruchomić ten skrypt i sprawdzić zgłoszoną liczbę przetworzonych klas, aby upewnić się, że wszystko jest zsynchronizowane.
Jeśli kiedykolwiek będziesz musiał usunąć ograniczenia i indeksy zarządzane przez neomodel, istnieje uzupełniające polecenie o nazwie neomodel_remove_labels. Ten skrypt automatycznie usuwa wszystkie istniejące ograniczenia i indeksy, które neomodel zainstalował wcześniej. Wyświetla również usunięte ograniczenia, dzięki czemu wyraźnie widać efekt operacji.
Oba polecenia zarządzania schematem obsługują --db argument i domyślnie NEO4J_BOLT_URL zmienna środowiskowa, jeśli nie jest podana. Takie zachowanie pomaga w ukryciu danych uwierzytelniających i szczegółów połączenia w historii wiersza poleceń oraz umożliwia prostą konfigurację za pomocą zmiennych środowiskowych. Ułatwia również zarządzanie skryptami automatyzacji i wdrażania.
Oprócz tworzenia schematu neomodel zawiera narzędzie do inspekcji bazy danych, które może przeprowadzić inżynierię wsteczną istniejącego grafu i wygenerować plik modelu. Korzystanie z inspect polecenie (które wymaga procedur APOC zainstalowanych w Neo4j) umożliwia przeskanowanie bazy danych i wygenerowanie models.py plik w katalogu docelowym, takim jak yourappWygenerowany plik zawiera importy, definicje klas węzłów i definicje relacji, które odpowiadają wykrytej strukturze grafu.
Proces kontroli można dostosować do dużych grafów, pomijając właściwości relacji i skanowanie kardynalności. W przypadku baz danych z setkami tysięcy węzłów i ponad milionem relacji pełne skanowanie może zająć dziesiątki sekund. Opcje takie jak --no-rel-props oraz --no-rel-cardinality Przyspiesz proces, pomijając szczegółową analizę, nadal generując pola relacji, ale ustawiając domyślną kardynalność na wartość ogólną, taką jak ZeroOrMore.
Praca z interfejsem API zapytań neomodel
Interfejs API zapytań Neomodel umożliwia wykonywanie złożonych zapytań graficznych za pomocą metod języka Python w klasach modelu, bez konieczności bezpośredniego pisania kodu w języku Cypher. Każdy model eksponuje .nodes Atrybut o charakterze menedżera, który reprezentuje zestaw węzłów z odpowiadającą im etykietą. Stamtąd możesz zliczać, filtrować, porządkować, wycinać i pobierać dane z wykresu.
powołanie len(MyModel.nodes) wyzwala zapytanie Cypher, które zlicza węzły z etykietą odpowiadającą MyModel. Oferuje intuicyjny sposób na uzyskanie liczby węzłów bez konieczności opuszczania składni Pythona. Jeśli zestaw węzłów jest już przefiltrowany, liczba będzie odzwierciedlać tylko węzły spełniające te filtry, co jest zgodne z zachowaniem typowym dla ORM.
Podział jest obsługiwany bezpośrednio na zestawy węzłów, co jest niezwykle przydatne, gdy chcesz pracować z wynikami wsadowymi. Wyrażenia takie jak MyModel.nodes[0:10] Zwraca wycinek zestawu węzłów, który można iterować lub łączyć z dodatkowymi filtrami. Wycinek nie zwraca od razu surowej listy, ale kolejny obiekt zestawu węzłów, dzięki czemu można budować złożone zapytania krok po kroku.
Zestawy węzłów obsługują iteracje i sprawdzanie wartości logicznych, chociaż operacje na długości i prawdziwości są operacjami końcowymi. Po dokonaniu oceny len() lub użyj zestawu węzłów w kontekście boolowskim, w efekcie uruchamiasz krok ewaluacji, który zwraca konkretny wynik, a nie kolejny obiekt zapytania, który można połączyć łańcuchowo. Ten projekt równoważy idiomy Pythona z leniwą naturą budowania zapytań.
Do pobierania rzeczywistych obiektów zazwyczaj stosuje się metody takie jak: .all() oraz .get() na .nodes manager. Te metody mogą otrzymać lazy=True Argument zwracający tylko identyfikatory węzłów zamiast pełnych obiektów i wszystkich ich właściwości. Jest to przydatne, jeśli chcesz zminimalizować transfer danych lub ręcznie wykonywać zapytania uzupełniające na podstawie identyfikatorów.
Tworzenie, aktualizowanie, usuwanie i relacje
Tworzenie węzłów za pomocą neomodelu jest tak proste, jak utworzenie instancji klasy modelu i wywołanie save(). Po zdefiniowaniu właściwości i ustawień domyślnych możesz utworzyć instancję z żądanymi wartościami pól i wywołać save, a neomodel utworzy lub zaktualizuje odpowiedni węzeł w Neo4j. Jest to analogiczne do sposobu, w jaki większość systemów ORM obsługuje trwałość.
Aktualizacja węzłów przebiega według tego samego schematu: pobieranie instancji, przypisywanie nowych wartości do jej atrybutów i ponowne zapisywanie. Neomodel dba o wygenerowanie odpowiedniego Cyphera, który modyfikuje tylko zmienione właściwości istniejącego węzła. Takie podejście sprawia, że kod jest przejrzysty, a szczegóły operacji aktualizacji nie wpływają na logikę biznesową.
Usuwanie węzła jest również bezpośrednie: gdy masz już instancję, wywołujesz jej delete() Metoda. Spowoduje to usunięcie węzła i, w zależności od konfiguracji relacji i ograniczeń bazy danych, może również spowodować usunięcie dołączonych relacji. Można zdefiniować haki przed i po usunięciu, aby uzyskać bardziej zaawansowane funkcje lub rejestrowanie.
Relacje między węzłami są zarządzane za pomocą pól relacji i wygodnych metod, takich jak: connect(). Gdy masz dwa węzły, możesz wywołać coś takiego actor.movies.connect(movie) aby utworzyć odpowiednią instancję relacji na wykresie. Właściwości relacji można modelować za pomocą StructuredRel-oparte na klasach, co daje możliwość przechowywania atrybutów również na krawędziach.
Bardziej złożone przeglądanie grafu można wykonać, śledząc atrybuty relacji lub łącząc filtry zapytań w ramach relacji. Na przykład możesz zacząć od Entity zestaw węzłów, filtruj według jakiejś właściwości, a następnie przejdź do powiązanych węzłów, aby filtrować również ich atrybuty. Stopniowo tworzy to zapytanie Cypher, które neomodel wykonuje w Twoim imieniu.
Asynchroniczny neomodel i transpilowany interfejs API synchronizacji
Neomodel obejmuje obsługę asynchroniczną zbudowaną na bazie możliwości asynchronicznych oficjalnego sterownika Neo4j dla języka Python. Oznacza to, że można zintegrować operacje Neo4j z nowoczesnymi asynchronicznymi strukturami i usługami Python, w pełni wykorzystując współbieżność w przypadku obciążeń obejmujących wiele operacji wejścia/wyjścia.
Testy wydajności przeprowadzone przy użyciu narzędzi takich jak Locust wykazały, że asynchroniczny neomodel, gdy jest używany jednocześnie, daje lepsze wyniki niż zapytania szeregowe i współbieżnie wykonywane synchroniczne wywołania neomodelu. Ponieważ wiele operacji grafowych obejmuje operacje wejścia/wyjścia sieciowego i oczekiwanie na odpowiedzi bazy danych, umożliwienie pętli zdarzeń obsługi wielu zapytań jednocześnie zapewnia lepszą przepustowość i wykorzystanie zasobów.
Neomodel wewnętrznie dba o zgodność interfejsów API asynchronicznych i synchronicznych, wykorzystując krok transpilacji, który konwertuje kod asynchroniczny na jego odpowiednik synchroniczny. Do automatycznego usuwania danych używana jest dedykowana biblioteka await słowa kluczowe, zmień nazwy klas (na przykład usuwając Async prefiksów) i wykonywać ukierunkowane wymiany, takie jak zmiana adb do db or mark_async_test do mark_sync_testDzięki takiemu podejściu unika się konieczności utrzymywania dwóch całkowicie oddzielnych baz kodu.
Wnosząc swój wkład, pracujesz głównie nad asynchroniczną implementacją neomodel/async_ a następnie uruchom dostarczony skrypt transpilacji, aby wygenerować wariant synchronizacji. Możesz również skorzystać z haków pre-commit, aby zautomatyzować ten krok i zapewnić synchronizację obu wersji. W wielu przypadkach logika biznesowa musi zostać napisana tylko raz w warstwie asynchronicznej.
Niektóre funkcjonalności mogą być przeznaczone wyłącznie do użytku asynchronicznego lub wyłącznie do użytku synchronicznego, a neomodel udostępnia wzorzec narzędzia (inspirowany oficjalnym sterownikiem Neo4j) w celu oddzielenia tych ścieżek kodu. Pozwala to zdefiniować zachowania różniące się w obu trybach, zachowując jednocześnie spójność całej powierzchni API. Moduły testowe, takie jak te obejmujące API dopasowania, demonstrują, jak kod asynchroniczny jest transpilowany i jak zachowuje się wynikowy kod synchronizacji.
Singletony bazy danych i asymetrycznej bazy danych
W neomodelu 6, Database() oraz AsyncDatabase() Klasy są implementowane jako prawdziwe singletony, aby wyjaśnić, w jaki sposób obsługiwane są operacje globalne. Zamiast rozpraszać niezależne funkcje narzędziowe, neomodel grupuje teraz operacje obejmujące całą bazę danych w pojedyncze instancje, dzięki czemu API staje się łatwiejsze do odnalezienia i bardziej spójne.
Kilka starszych funkcji zostało przeniesionych do Database() klasę i usunięto ją z globalnej przestrzeni nazw. Przykłady obejmują change_neo4j_password, clear_neo4j_database, drop_constraints, drop_indexes, remove_all_labels, install_labels, install_all_labels. Odpowiedniki asynchroniczne są dostępne z AsyncDatabase() singleton, zwykle określany jako adb w kontekście asynchronicznym.
To nowe rozwiązanie upraszcza modele mentalne dotyczące operacji na poziomie bazy danych i pozwala uniknąć niejednoznaczności w sposobie obsługi konfiguracji i stanu globalnego. Dzięki zapewnieniu, że tryby synchronizacji i asynchroniczności mają podobną strukturę, łatwiej jest również ocenić, kiedy można bezpiecznie przełączyć się z jednego podejścia na drugie lub uruchomić je równolegle w różnych częściach większej aplikacji.
Ponadto wersja 6.0 wprowadziła: merge_by parametr dla operacji wsadowych, zapewniający większą kontrolę nad sposobem scalania węzłów i relacji. Można dostosować, które etykiety i klucze właściwości definiują unikatowość scalania wsadowego, co jest niezwykle istotne przy obsłudze dużych ilości zadań związanych z pozyskiwaniem danych lub synchronizacją.
Integracja Django i praktyczne zastosowanie
Neomodel integruje się czysto z Django poprzez django_neomodel pakiet umożliwiający traktowanie modeli grafów jako części projektu Django. Dzięki tej integracji konfiguracja zazwyczaj znajduje się w settings.py, a Twoje klasy węzłów i relacji współistnieją z resztą ekosystemu Django, włączając w to aplikacje, oprogramowanie pośredniczące i widoki.
Konkretnym przykładem jest wieloczęściowy samouczek Django, w którym użyto neomodelu do eksploracji i przeszukiwania bazy danych grafów w stylu Paradise Papers. W pierwszych częściach konfigurujesz projekt Django i integrujesz neomodel; w późniejszych częściach budujesz fetch_api aplikacji, zdefiniuj modele odzwierciedlające jednostki, relacje i właściwości na wykresie, a następnie stopniowo buduj na ich podstawie narzędzia i widoki.
W ramach takiego projektu można używać modeli neomodel bezpośrednio w widokach Django, serializatorach lub modułach pomocniczych. Powszechnym podejściem jest stworzenie utils.py Plik, w którym definiujesz funkcje ułatwiające korzystanie z API zapytań. Na przykład możesz zaimplementować count_nodes, fetch_nodes, fetch_node_details pomocnicy, którzy dynamicznie pobierają filtry, parametry paginacji i nazwy modeli.
Niektóre dane, takie jak listy krajów, jurysdykcji lub źródeł danych, mogą być kosztowne w wielokrotnym wyszukiwaniu, dlatego można je obliczyć wstępnie przy użyciu surowego Cyphera i zapisać jako stałe. A constants.py moduł może wykonać te zapytania Cypher raz, wyprowadzić posortowane listy jak COUNTRIES, JURISDICTIONS, DATASOURCEi umożliwić ich łatwe importowanie do aplikacji Django.
Aby mieć pewność, że te stałe będą gotowe podczas uruchamiania aplikacji, możesz połączyć się z konfiguracją aplikacji Django, definiując ready() metoda w fetch_api/app.py. W ramach tej metody importujesz constants.py, który uruchamia początkowe zapytania Cypher i wypełnia odpowiednie listy. W ten sposób kolejne zapytania mogą po prostu odczytywać dane z już przygotowanych struktur.
Surowy Cypher kontra OGM dla złożonych zapytań
Chociaż OGM neomodelu idealnie nadaje się do codziennego przetwarzania CRUD i przeglądania relacji, istnieją scenariusze, w których ręcznie napisane zapytania Cypher są bardziej wydajne. Głęboko zagnieżdżone przejścia, zapytania drugiego stopnia lub wieloskokowe i zaawansowane agregacje można czasami wyrazić wyraźniej i wydajniej przy użyciu surowego Cypher niż łańcuchów OGM.
Typowym przykładem jest znalezienie aktorów, którzy wystąpili w jakimś filmie u boku konkretnego aktora, np. ustalenie wszystkich osób, które współpracowały z Tomem Hanksem. W przypadku zapytania Cypher może to być dość bezpośrednie: dopasowujesz aktora, przechodzisz do filmów, w których wystąpił, a następnie do innych aktorów w tych filmach, stosując filtry i agregacje w razie potrzeby. Rezultatem jest zwięzły, zoptymalizowany wzór grafu.
Powtórzenie tego samego zachowania wyłącznie za pomocą wygodnych metod OGM może wymagać procesu w stylu O(n²), pętli po filmach i powiązanych aktorach na poziomie języka Python. Jest to zarówno mniej eleganckie, jak i mniej wydajne niż pozostawienie Neo4j wykonywania dużej ilości zadań w jednym poleceniu Cypher. Pokazuje to, że OGM-y nie są idealnym rozwiązaniem dla każdego wzorca dostępu do grafu.
Co więcej, gdy opierasz się na operacjach OGM przy głębokich przeglądach, kształt zwracanych danych może stać się dość skomplikowany. Wygenerowany Cypher często zawiera węzeł początkowy, relacje pośrednie, węzły sąsiednie i ich relacje. Może to być przydatne, gdy potrzebujesz bogatego kontekstu, ale może być przesadą, gdy potrzebujesz tylko określonych zagregowanych wyników lub podzbioru właściwości.
W sytuacjach, w których najważniejsza jest wydajność i przejrzystość, należy użyć cypher_query bezpośrednie wykonanie ręcznie stworzonego Cyphera może być lepszą opcją. Neomodel celowo stworzył taką możliwość: możesz mieszać i dopasowywać interakcje OGM wysokiego poziomu z interakcjami Cypher niskiego poziomu w tym samym projekcie, wybierając właściwe narzędzie dla każdego konkretnego zapytania, a jednocześnie traktując modele jako jedyne źródło prawdy dla swojego schematu.
Neomodel w Neo4j Labs i zarządzanie projektem
Wejście Neomodel do programu Neo4j Labs sformalizowało jego status jako aktywnie utrzymywanego, prowadzonego przez społeczność projektu z jasno określonymi oczekiwaniami co do jakości. Neo4j Labs to miejsce dla eksperymentalnych i zaawansowanych projektów, które mają realną siłę przebicia, ale nie są częścią głównego produktu. Wiele znanych narzędzi, takich jak komponenty grafowej nauki o danych, biblioteka GraphQL, rdzeń APOC i integracje strumieniowe, ma swoje korzenie w tym programie.
Przynależność do Neo4j Labs oznacza, że neomodel przestrzega podstawowych standardów dotyczących testowania, kontroli bezpieczeństwa i zautomatyzowanych narzędzi, takich jak procesy CI/CD. Zespół konserwacyjny przeprowadza testy integracyjne z wykorzystaniem szerokiej gamy wersji Pythona i Neo4j, zapewniając kompatybilność w miarę pojawiania się nowych wydań. To jeden z powodów, dla których neomodel może pochwalić się pełnym wsparciem dla wszystkich obecnie obsługiwanych wersji Pythona i Neo4j, zarówno Community, jak i Enterprise.
Projekt pozostaje w pełni otwarty i skoncentrowany na społeczności, przy czym GitHub stanowi główne centrum zgłaszania problemów, dyskusji i przekazywania opinii. Dziennik zgłoszeń jest ponownie aktywnie aktualizowany, a starsze elementy są selekcjonowane i podsumowywane w miarę możliwości czasowych. Strefa Dyskusji jest otwarta dla wszystkich i służy do zamieszczania ogłoszeń i rozmów projektowych. Co najmniej jeden pracownik Neo4j pełni funkcję opiekuna, łącząc doświadczenie terenowe z projektem.
Rzeczywiste wdrożenia produkcyjne, takie jak OpenStudyBuilder firmy Novo Nordisk, odgrywają ważną rolę w kształtowaniu planu działania neomodelu. Te wielkoskalowe, rzeczywiste aplikacje dostarczają konkretnych wymagań i informacji zwrotnych, które przekładają się na nowe funkcje i ulepszenia, przekazywane społeczności. Ta pętla korzyści pokazuje, jak użytkowanie korporacyjne i rozwój oprogramowania open source mogą się wzajemnie wzmacniać.
Dzięki modelowaniu w języku Python, solidnemu dopasowaniu do Neo4j, asynchronicznym i synchronicznym interfejsom API oraz aktywnej ewolucji wspieranej przez środowisko laboratoryjne, neomodel oferuje atrakcyjny sposób pracy z grafami w języku Python zarówno w małych projektach, jak i wymagających systemach produkcyjnych. Użyty z rozwagą — wykorzystujący OGM do przejrzystego modelowania domen i typowych interakcji grafowych, a sięgający po surowy Cypher, gdy wymagają tego złożone wzorce lub wydajność — może znacznie uprościć projektowanie, tworzenie zapytań i utrzymywanie aplikacji opartych na grafach.