2012-03-26 11 views
5

To jest bardziej właściwie pytanie Lucene, ale jest w kontekście bazy danych neo4j.Indeksowanie Neo4j (z Lucene) - dobry sposób na uporządkowanie "typów" węzłów?

Mam bazę danych, która jest podzielona na około 50 typów węzłów (więc "kolekcje" lub "tabele" w innych typach dbs). Każdy ma podzbiór właściwości, które muszą być indeksowane, niektóre mają tę samą nazwę, inne nie.

Podczas wyszukiwania zawsze chcę znaleźć węzły określonego typu, nigdy we wszystkich węzłach.

Widzę trzy sposoby organizowania tego:

  • jeden indeks danego rodzaju, właściwości map naturalnie do pól indeksów: indeksu 'foo', 'id'='1234'.

  • Pojedynczy wskaźnik globalny, każdy mapy terenowe do nazwy własności, aby odróżnić typ albo dołączyć je jako część wartości ('id'='foo:1234') lub sprawdzić węzły raz oni wrócili (duplikaty Spodziewam się bardzo rzadko).

  • Pojedynczy indeks, typ jest częścią nazwy pola: 'foo.id'='1234'.

Po utworzeniu baza danych jest tylko do odczytu.

Czy są jakieś korzyści pod względem wygody, wydajności/wydajności pamięci podręcznej/pamięci podręcznej?

Jak rozumiem, dla pierwszej opcji neo4j utworzy osobny indeks fizyczny dla każdego typu, który wydaje się nieoptymalny. Po trzecie, kończę z większością lucene docs tylko mając mały podzbiór pól, nie jestem pewien czy to wpływa na cokolwiek.

+0

Posiadanie osobnego indeksu dla każdego typu wydaje się wygodniejsze i szybsze, ponieważ ogólny rozmiar indeksu będzie mniejszy. Ale może czegoś brakuje. – biziclop

+0

@biziclop: Wydawało mi się to najmniej wygodne dla mnie, ponieważ musiałbym zarządzać otwieraniem/zamykaniem poszczególnych indeksów. Rozumiem, że ogólny rozmiar również będzie większy (patrz odpowiedź jpountza). – Dmitri

+0

@Dimitri Cóż, oczywiście ogólny rozmiar będzie większy, pytanie brzmi: czy wyszukuje wszystkie typy równo rozłożone w czasie? Czy niektóre typy są wyszukiwane dużo częściej niż inne? Tak czy inaczej, chciałbym wdrożyć rozwiązanie, które uważam za najwygodniejsze i sprawdzić, czy działa dobrze. Jeśli tak, masz swojego zwycięzcę. – biziclop

Odpowiedz

1

Pojedynczy indeks będzie mniejszy niż kilka małych indeksów, ponieważ niektóre dane, takie jak termin słownik, zostaną udostępnione. Ponieważ jednak terminem wyszukiwania słownika jest operacja O (lg (n)), wyszukiwanie w słowniku o większej liczbie terminów może być nieco wolniejsze. (Jeśli masz 50 indeksów, wymagałoby to tylko 6 (2^6 = 50) więcej porównań, prawdopodobnie nie zauważysz żadnej różnicy.)

Kolejną zaletą mniejszego indeksu jest to, że pamięć podręczna systemu operacyjnego prawdopodobnie sprawi, że zapytania będą działały szybciej.

Zamiast opcji 2 i 3, chciałbym indeks dwa różne pola id i type i poszukiwania (id: Identyfikator I type: TYPE), ale nie wiem, czy jest to możliwe z neo4j.

+0

Korzystanie z wielu pól jest możliwe, ale trochę mniej naturalne (dlatego to opuściłem): można przekazać zapytanie dotyczące konkretnej implementacji ciąg bezpośrednio do silnika indeksu.Wolałbym użyć bardziej ogólnego API 'index.get (field, value)'. – Dmitri

+0

Następnie wybrałbym drugą opcję, która jest najbardziej naturalna (id: TYPE + ID) – jpountz

1

Spring-data-neo4j wykorzystuje pierwsze podejście - tworzy inny indeks dla każdego typu. Sądzę, że to dobra opcja dla ogólnego scenariusza. Ale w twoim konkretnym przypadku może to być suboptymalne, jak mówisz. Przeprowadziłbym testy porównawcze, aby zmierzyć wydajność.

Pozostałe dwie, nawiasem mówiąc, wydają się nieco sztuczne. Prawdopodobnie indeksujesz całkowicie niepowiązane informacje w tym samym indeksie, co nie brzmi dobrze.

+0

Nie jestem pewien, czy widzę problem z indeksowaniem niepowiązanych danych razem - gdyby była to relacyjna baza danych, na przykład większość tych właściwości byłaby prawdopodobnie zindeksowana w jednej tabeli "wartości atrybutów". – Dmitri

+0

tak, może masz rację. Indeksowanie pełnotekstowe jest dziwne, ale ponieważ używasz go jako indeksu wspierającego sklep neo4j, nie brzmi tak źle. – Bozho

2

Ostatnio napotkałem ten problem, kiedy budowałem adapter połączenia ActiveRecord dla Neo4j nad REST, do wykorzystania w projekcie Rails. Od ActiveRecord i ActiveRelation, oba mają ścisłe połączenie z syntax SQL, trudno było dopasować wszystko do NoSQL.może nie być najlepszym rozwiązaniem, ale oto jak I rozwiązać go:

  1. Utworzono indeks o nazwie model_index które indeksowane węzły pod dwoma kluczami, type i model
  2. odnośnika indeksu z type klucz aktualnie dzieje się z tylko jednej wartości model . Zostało to wprowadzone przede wszystkim w celu uzyskania funkcji SQL w wersji SHOW TABLES, dzięki której mogę wyświetlić listę wszystkich modeli obecnych na wykresie.
  3. Wyszukiwanie indeksu z kluczem model odbywa się z wartościami odpowiadającymi różnym nazwom modelu w moim systemie. Jest to przede wszystkim do osiągnięcia funkcjonalności DESC <TABLENAME>.
  4. Przy każdym utworzeniu tabeli, jak w CREATE TABLE, tworzony jest węzeł z atrybutami definicji tabeli przechowywanymi we właściwościach węzła.
  5. Utworzony węzeł jest indeksowany pod model_index z type:model i model:<model-name>. Umożliwia to nowo utworzony model na liście "tabel", a także pozwala bezpośrednio dotrzeć do węzła modelu poprzez wyszukiwanie indeksu za pomocą klucza model.
  6. Dla każdego rekordu utworzonego na model (wpisz w twoim przypadku), krawędź wychodząca jest tworzona z etykietą instances skierowaną od węzła modelu do nowego rekordu. v[123] :=> [instances] :=> v[245] gdzie v [123] reprezentuje węzeł modelu, a v [245] oznacza rekord typu v [123].
  7. Teraz, jeśli chcesz uzyskać wszystkie wystąpienia określonego typu, możesz odszukać model_index za pomocą model:<model-name>, aby uzyskać dostęp do węzła modelu, a następnie pobrać wszystkie sąsiednie węzły na wychodzącej krawędzi oznaczonej instances. Przeszukane wyszukiwania można dodatkowo osiągnąć, stosując filtry i inne skomplikowane przejścia.

Powyższe rozwiązanie zapobiega zapychaniu się wskaźnika_modelu, ponieważ zawiera ono wartość 2x i umożliwia skuteczne wyszukiwanie rekordów za pomocą jednego wyszukiwania indeksu i przejścia pojedynczego poziomu.

Chociaż w twoim przypadku węzły różnych typów nie sąsiadują ze sobą, nawet jeśli chcesz to zrobić, możesz określić typ dowolnego dowolnego węzła, po prostu patrząc na sąsiedni węzeł z przychodzącą krawędzią o nazwie instances. . Ponadto rozważam włączenie wzoru SpringDataGraph przechowywania właściwości __type__ na każdym węźle instancji, aby uniknąć tego sąsiedniego wyszukiwania węzłów.

Obecnie tłumaczę AREL na skrypty Gremlin dla prawie wszystkiego. Możesz znaleźć kod źródłowy mojego adaptera AR pod adresem https://github.com/yournextleap/activerecord-neo4j-adapter

Mam nadzieję, że to pomaga, Pozdrawiam! :)

+0

To brzmi jak moja opcja "2b": zindeksuj wszystko razem i użyj wykresu do filtrowania dla typu (albo z sprawdzaniem krawędzi, albo, jak sugerujesz, właściwością typu). Myślę, że skłaniam się ku opcji 3, aby filtrowane wyszukiwanie mogło być wykonane całkowicie w indeksie. – Dmitri

+0

Jedną z wad polegania na zbyt dużej indeksacji jest to, że kiedy trzeba wyeksportować wykres, w GraphML lub GraphSON, z których żaden nie zachowuje indeksów, należy zregenerować indeksy po zaimportowaniu wykresu gdzie indziej. Indeksowanie wszystkiego na wykresie może oznaczać długi czas na eksport -> import. Ponadto, jeśli istnieje podgraph, który jest odłączony od węzła głównego, utrata indeksów w takim przypadku może oznaczać utratę danych i pozostaniesz bez opcji niezawodny dostęp do subgraph. – rhetonik

+0

Dlatego radzę, aby wszystkie węzły były przeszukiwane z węzła głównego, na wypadek, gdyby zaimportowano wykres z wcześniej wyeksportowanego GraphML/SON. – rhetonik

Powiązane problemy