Szukaj…


Uwagi

Łatwo jest zobaczyć type takie jak tabela w bazie danych SQL, gdzie index jest baza danych SQL. Nie jest to jednak dobry sposób podejścia do type s.

Wszystkie typy

W rzeczywistości typy są dosłownie tylko polami metadanych dodawanymi do każdego dokumentu przez Elasticsearch: _type . Powyższe przykłady stworzyły dwa typy: my_type i my_other_type . Oznacza to, że każdy dokument powiązany z typami ma automatycznie zdefiniowane dodatkowe pole, takie jak "_type": "my_type" ; jest to indeksowane wraz z dokumentem, co czyni go polem przeszukiwalnym lub filtrowalnym , ale nie wpływa na sam surowy dokument, więc aplikacja nie musi się o to martwić.

Wszystkie typy żyją w tym samym indeksie, a zatem w tych samych zbiorczych fragmentach indeksu. Nawet na poziomie dysku znajdują się w tych samych plikach. Jedyne rozdzielenie, jakie zapewnia utworzenie drugiego typu, jest logiczne. Każdy typ, czy to unikalny, czy nie, musi istnieć w mapowaniach, a wszystkie te mapowania muszą istnieć w stanie klastra. To zużywa pamięć, a jeśli każdy typ jest dynamicznie aktualizowany, zwiększa wydajność wraz ze zmianą mapowań.

W związku z tym najlepszą praktyką jest definiowanie tylko jednego typu, chyba że faktycznie potrzebujesz innych typów. Często spotyka się scenariusze, w których pożądanych jest wiele typów. Na przykład wyobraź sobie, że masz indeks samochodu. Przydaje się podział na wiele typów:

  • BMW
  • pogoń
  • Honda
  • mazda
  • mercedes
  • Nissan
  • rangerover
  • Toyota
  • ...

W ten sposób możesz wyszukać wszystkie samochody lub ograniczyć je według producenta na żądanie. Różnica między tymi dwoma wyszukiwaniami jest tak prosta, jak:

GET /cars/_search

i

GET /cars/bmw/_search

Dla nowych użytkowników Elasticsearch nie jest oczywiste, że druga forma jest specjalizacją pierwszej formy. Dosłownie zostaje przepisany na:

GET /cars/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term" : {
            "_type": "bmw"
          }
        }
      ]
    }
  }
}

Po prostu odfiltrowuje każdy dokument, który nie został zindeksowany za pomocą pola _type którego wartość to bmw . Ponieważ każdy dokument jest indeksowany ze swoim typem jako pole _type , służy to jako dość prosty filtr. Jeśli w którymkolwiek z przykładów podano rzeczywiste wyszukiwanie, filtr zostałby odpowiednio dodany do pełnego wyszukiwania.

W związku z tym, jeśli typy są identyczne, o wiele lepiej jest podać jeden typ (np. manufacturer w tym przykładzie) i skutecznie go zignorować. Następnie w każdym dokumencie wyraźnie podaj pole o nazwie make lub dowolna nazwa i ręcznie filtruj je, gdy tylko chcesz. Zmniejszy to rozmiar twoich mapowań do 1/n gdzie n jest liczbą oddzielnych typów. Dodaje kolejne pole do każdego dokumentu na korzyść skądinąd uproszczonego mapowania.

W Elasticsearch 1.xi 2.x takie pole należy zdefiniować jako

PUT /cars
{
  "manufacturer": { <1>
    "properties": {
      "make": { <2>
        "type": "string",
        "index": "not_analyzed"
      }
    }
  }
}
  1. Nazwa jest dowolna.
  2. Nazwa jest dowolna i może być zgodna z nazwą typu, jeśli jej również chcesz.

W Elasticsearch 5.x powyższe będzie nadal działać (jest przestarzałe), ale lepszym sposobem jest użycie:

PUT /cars
{
  "manufacturer": { <1>
    "properties": {
      "make": { <2>
        "type": "keyword"
      }
    }
  }
}
  1. Nazwa jest dowolna.
  2. Nazwa jest dowolna i może być zgodna z nazwą typu, jeśli jej również chcesz.

Typy powinny być stosowane oszczędnie w obrębie indeksów, ponieważ nadymają odwzorowania indeksów, zwykle bez większych korzyści. Musisz mieć co najmniej jeden, ale nic nie mówi, że musisz mieć więcej niż jeden.

Często zadawane pytania

  • Co jeśli mam dwa (lub więcej) typy, które są w większości identyczne, ale które mają kilka unikalnych pól dla każdego typu?

Na poziomie indeksu nie ma różnicy między jednym typem używanym z kilkoma rzadko używanymi polami a między wieloma typami, które współużytkują kilka nierzadkich pól z kilkoma nieudostępnionymi (co oznacza, że drugi typ nigdy nie używa pola (s)).

Inaczej mówiąc: rzadko używane pole jest rzadkie w całym indeksie, niezależnie od typów . Rzadkość nie korzysta - ani nie szkodzi - indeksowi tylko dlatego, że jest zdefiniowany w osobnym typie.

Powinieneś po prostu połączyć te typy i dodać osobne pole typu.

  • Dlaczego osobne typy muszą definiować pola dokładnie w ten sam sposób?

Ponieważ każde pole jest tak naprawdę zdefiniowane tylko raz na poziomie Lucene, bez względu na liczbę typów. Fakt, że typy w ogóle istnieją, jest cechą Elasticsearch i jest tylko logiczną separacją.

  • Czy mogę zdefiniować osobne typy z tym samym polem zdefiniowanym inaczej?

Nie. Jeśli uda ci się znaleźć sposób na wykonanie tego w ES 2.x lub nowszej, powinieneś otworzyć raport o błędzie . Jak zauważono w poprzednim pytaniu, Lucene traktuje je wszystkie jako jedno pole, więc nie ma sposobu, aby działało to odpowiednio.

ES 1.x pozostawił to jako domniemane wymaganie, które pozwoliło użytkownikom stworzyć warunki, w których odwzorowania jednego fragmentu w indeksie faktycznie różniły się od innego fragmentu w tym samym indeksie. To był w rzeczywistości wyścig i może prowadzić do nieoczekiwanych problemów.

Wyjątki od reguły

  • Dokumenty nadrzędne / podrzędne wymagają stosowania oddzielnych typów w ramach tego samego indeksu.
    • Rodzic mieszka w jednym typie.
    • Dziecko żyje w osobnym typie (ale każde dziecko żyje w tym samym odłamku, co jego rodzic).
  • Niezwykle niszowe przypadki użycia, w których tworzenie ton indeksów jest niepożądane, a wpływ rzadkich pól jest lepszy niż alternatywa.
    • Na przykład wtyczka monitorująca Elasticsearch, Marvel (1.x i 2.x) lub X-Pack Monitoring (5.x +), sam monitoruje Elasticsearch pod kątem zmian w klastrze, węzłach, indeksach, określonych indeksach (poziom indeksu), a nawet odłamki. Może tworzyć ponad 5 indeksów każdego dnia, aby wyodrębnić te dokumenty, które mają unikalne mapowania, lub może być sprzeczny z najlepszymi praktykami w celu zmniejszenia obciążenia klastra poprzez udostępnienie indeksu (uwaga: liczba zdefiniowanych mapowań jest faktycznie taka sama, ale liczba utworzonych indeksów jest zmniejszona z n do 1).
    • To jest zaawansowany scenariusz, ale musisz wziąć pod uwagę wspólne definicje pól dla różnych typów!

Jawne tworzenie indeksu z typem

Przykład wykorzystuje podstawowy HTTP, który łatwo przekłada się na cURL i inne aplikacje HTTP. Pasują również do składni Sense , której nazwa zostanie zmieniona na Console w Kibana 5.0.

Uwaga: Przykład wstawia <#> aby pomóc zwrócić uwagę na części. Należy je usunąć, jeśli go skopiujesz!

PUT /my_index <1>
{
  "mappings": {
    "my_type": { <2>
      "properties": {
        "field1": {
          "type": "long"
        },
        "field2": {
          "type": "integer"
        },
        "object1": {
          "type": "object",
          "properties": {
            "field1" : {
              "type": "float"
            }
          }
        }
      }
    }
  },
  "my_other_type": {
    "properties": {
      "field1": {
        "type": "long" <3>
      },
      "field3": { <4>
        "type": "double"
      }
    }
  }
}
  1. To jest tworzenie index przy użyciu punktu końcowego tworzenia indeksu.
  2. To tworzy ten type .
  3. Wspólne pola type s w ramach tego samego index muszą mieć tę samą definicję! ES 1.x nie narzucał ściśle tego zachowania, ale był to wymóg dorozumiany. ES 2.x i wyżej ściśle egzekwują to zachowanie.
  4. Unikalne pola w różnych type są w porządku.

Indeksy (lub indeksy) zawierają typy. Typy są wygodnym mechanizmem rozdzielania dokumentów, ale wymagają zdefiniowania - dynamicznie / automatycznie lub jawnie - mapowania dla każdego używanego typu. Jeśli zdefiniujesz 15 typów w indeksie, masz 15 unikalnych mapowań.

Zobacz uwagi, aby uzyskać więcej informacji na temat tej koncepcji i dlaczego możesz chcieć używać typów.

Dynamiczne tworzenie indeksu z typem

Przykład wykorzystuje podstawowy HTTP, który łatwo przekłada się na cURL i inne aplikacje HTTP. Pasują również do składni Sense , której nazwa zostanie zmieniona na Console w Kibana 5.0.

Uwaga: Przykład wstawia <#> aby pomóc zwrócić uwagę na części. Należy je usunąć, jeśli go skopiujesz!

DELETE /my_index <1>

PUT /my_index/my_type/abc123 <2>
{
  "field1" : 1234, <3>
  "field2" : 456,
  "object1" : {
    "field1" : 7.8 <4>
  }
}
  1. Jeśli już istnieje (z powodu wcześniejszego przykładu), usuń indeks.
  2. Indeksuj dokument do indeksu, my_index , za pomocą typu, my_type i identyfikatora abc123 (może być numeryczny, ale zawsze jest łańcuchem).
    • Domyślnie dynamiczne tworzenie indeksu jest włączane po prostu przez indeksowanie dokumentu. Jest to świetne rozwiązanie dla środowisk programistycznych, ale niekoniecznie jest dobre dla środowisk produkcyjnych.
  3. To pole jest liczbą całkowitą, więc po raz pierwszy musi zostać zmapowane. Elasticsearch zawsze zakłada najszerszy typ dla dowolnego typu przychodzącego, więc byłby on odwzorowany jako long a nie integer lub short (oba mogą zawierać 1234 i 456 ).
  4. To samo dotyczy również tego pola. Zostanie zmapowany jako double zamiast float jak możesz chcieć.

Ten dynamicznie tworzony indeks i typ z grubsza odpowiadają odwzorowaniu zdefiniowanemu w pierwszym przykładzie. Jednak ważne jest, aby zrozumieć, w jaki sposób <3> i <4> wpływają na automatycznie zdefiniowane odwzorowania.

Możesz to zrobić, dynamicznie dodając kolejny typ do tego samego indeksu:

PUT /my_index/my_other_type/abc123 <1>
{
  "field1": 91, <2>
  "field3": 4.567
}
  1. Typ jest jedyną różnicą w stosunku do powyższego dokumentu. Identyfikator jest taki sam i jest w porządku! Nie ma żadnego związku z innym abc123 poza tym, że akurat jest w tym samym indeksie.
  2. field1 już istnieje w indeksie, więc musi to być ten sam typ pola, co zdefiniowany w innych typach. Podanie wartości, która była łańcuchem lub nie była liczbą całkowitą, nie powiodło się (np. "field1": "this is some text" lub "field1": 123.0 ).

Spowodowałoby to dynamiczne tworzenie odwzorowań dla my_other_type w ramach tego samego indeksu, my_index .

Uwaga: Zawsze jest szybsze definiowanie odwzorowań z góry niż dynamiczne wykonywanie go w czasie indeksowania przez Elasticsearch.

Końcowy wynik indeksowania obu dokumentów byłby podobny do pierwszego przykładu, ale typy pól byłyby różne, a zatem nieco marnotrawne:

GET /my_index/_mappings <1>
{
  "mappings": {
    "my_type": { <2>
      "properties": {
        "field1": {
          "type": "long"
        },
        "field2": {
          "type": "long" <3>
        },
        "object1": {
          "type": "object",
          "properties": {
            "field1" : {
              "type": "double" <4>
            }
          }
        }
      }
    }
  },
  "my_other_type": { <5>
    "properties": {
      "field1": {
        "type": "long"
      },
      "field3": {
        "type": "double"
      }
    }
  }
}
  1. Używa punktu końcowego _mappings aby uzyskać mapowania z utworzonego przez nas indeksu.
  2. Dynamicznie utworzyliśmy my_type w pierwszym kroku tego przykładu.
  3. field2 jest teraz long zamiast liczby integer ponieważ nie zdefiniowaliśmy go z góry. Może to okazać się marnotrawstwem w przypadku przechowywania na dysku.
  4. object1.field1 jest teraz double z tego samego powodu co # 3 z tymi samymi konsekwencjami jak # 3.
    • Technicznie long można skompresować w wielu przypadkach. Jednak double nie można skompresować, ponieważ jest liczbą zmiennoprzecinkową.
  5. Dynamicznie utworzyliśmy także my_other_type w drugim kroku tego przykładu. Zdarza się, że mapowanie jest takie samo, ponieważ używaliśmy już long i double .
    • Pamiętaj, że field1 musi pasować do definicji z my_type (i tak jest).
    • field3 jest unikalny dla tego typu, więc nie ma takich ograniczeń.


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow