Elasticsearch je pretraživač sa json rest api, koji koristi Lucene i napisan na Javi. Opis svih prednosti ovog motora dostupan je na službena web stranica. U nastavku ćemo Elasticsearch nazivati ES.
Slični motori se koriste za složena pretraživanja u bazi podataka. Na primjer, pretraživanje uzimajući u obzir morfologiju jezika ili pretraživanje po geografskim koordinatama.
U ovom članku ću govoriti o osnovama ES-a na primjeru indeksiranja blog postova. Pokazat ću vam kako filtrirati, sortirati i pretraživati dokumente.
Da ne bih zavisio od operativnog sistema, sve zahteve ću uputiti ES-u koristeći CURL. Postoji i dodatak za Google Chrome koji se zove osjećaj.
Tekst sadrži linkove na dokumentaciju i druge izvore. Na kraju se nalaze linkovi za brzi pristup dokumentaciji. Definicije nepoznatih pojmova mogu se naći u glossarii.
Instaliranje ES
Da bismo to uradili, prvo nam je potrebna Java. Developers preporučeno instalirajte Java verzije novije od Java 8 ažuriranja 20 ili Java 7 ažuriranja 55.
# Добавим документ c id 1 типа post в индекс blog.
# ?pretty указывает, что вывод должен быть человеко-читаемым.
curl -XPUT "$ES_URL/blog/post/1?pretty" -d'
{
"title": "Веселые котята",
"content": "<p>Смешная история про котят<p>",
"tags": [
"котята",
"смешная история"
],
"published_at": "2014-09-12T20:44:42+00:00"
}'
ES automatski kreiran indeks blog i Tip pošta. Možemo povući uslovnu analogiju: indeks je baza podataka, a tip je tabela u ovoj bazi podataka. Svaki tip ima svoju shemu − kartografija, baš poput relacijske tablice. Mapiranje se generiše automatski kada se dokument indeksira:
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"
U odgovoru servera dodao sam vrijednosti polja indeksiranog dokumenta u komentarima:
Vrijedi napomenuti da ES ne pravi razliku između jedne vrijednosti i niza vrijednosti. Na primjer, polje naslova jednostavno sadrži naslov, a polje oznaka sadrži niz stringova, iako su oni predstavljeni na isti način u mapiranju.
Kasnije ćemo razgovarati više o mapiranju.
Zahtjevi
Preuzimanje dokumenta po njegovom ID-u:
# извлечем документ с id 1 типа post из индекса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
U odgovoru su se pojavili novi ključevi: _version и _source. Općenito, svi ključevi počinju sa _ klasifikovani su kao službeni.
Ključ _version prikazuje verziju dokumenta. To je potrebno da bi optimistični mehanizam za zaključavanje radio. Na primjer, želimo promijeniti dokument koji ima verziju 1. Predajemo izmijenjeni dokument i označavamo da je ovo izmjena dokumenta sa verzijom 1. Ako je neko drugi također uređivao dokument sa verzijom 1 i podnio izmjene prije nas, onda ES neće prihvatiti naše promjene, jer pohranjuje dokument s verzijom 2.
Ključ _source sadrži dokument koji smo indeksirali. ES ne koristi ovu vrijednost za operacije pretraživanja jer Za pretraživanje se koriste indeksi. Da uštedi prostor, ES pohranjuje komprimirani izvorni dokument. Ako nam je potreban samo id, a ne cijeli izvorni dokument, onda možemo onemogućiti izvornu memoriju.
Ako nam nisu potrebne dodatne informacije, možemo dobiti samo sadržaj _source:
curl -XPUT "$ES_URL/blog/post/3" -d'
{
"title": "Как у меня появился котенок",
"content": "<p>Душераздирающая история про бедного котенка с улицы<p>",
"tags": [
"котята"
],
"published_at": "2014-07-21T20:44:42+00:00"
}'
Sortiranje
# найдем последний пост по дате публикации и извлечем поля title и published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"size": 1,
"_source": ["title", "published_at"],
"sort": [{"published_at": "desc"}]
}'
Izabrali smo zadnji post. size ograničava broj dokumenata koji se izdaju. total prikazuje ukupan broj dokumenata koji odgovaraju zahtjevu. sort u izlazu sadrži niz cijelih brojeva po kojima se vrši sortiranje. One. datum je pretvoren u cijeli broj. Više informacija o sortiranju možete pronaći u dokumentaciju.
Filteri i upiti
ES od verzije 2 ne pravi razliku između filtera i upita uvodi se koncept konteksta.
Kontekst upita razlikuje se od konteksta filtera po tome što upit generiše _score i nije keširan. Kasnije ću vam pokazati šta je _score.
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'
Filtriranje po oznakama
Koristimo upit o terminu za traženje ID-ova dokumenata koji sadrže datu riječ:
# найдем все документы, в поле tags которых есть элемент 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": [
"title",
"tags"
],
"filter": {
"term": {
"tags": "котята"
}
}
}'
Međutim, ako tražimo "priče" u polju sadržaja, nećemo ništa pronaći, jer Indeks sadrži samo originalne riječi, ne i njihove osnove. Da biste izvršili kvalitetno pretraživanje, potrebno je konfigurirati analizator.
polje _score pokazuje relevantnost. Ako se zahtjev izvršava u kontekstu filtera, tada će vrijednost _score uvijek biti jednaka 1, što znači potpuno podudaranje s filterom.
Analizatori
Analizatori potrebni su za pretvaranje izvornog teksta u skup tokena.
Analizatori se sastoje od jednog Tokenizer i nekoliko opcionih TokenFilters. Tokenizer može prethoditi nekoliko CharFilters. Tokenizatori razbijaju izvorni niz u tokene, kao što su razmaci i znakovi interpunkcije. TokenFilter može promijeniti tokene, izbrisati ili dodati nove, na primjer, ostaviti samo korijen riječi, ukloniti prijedloge, dodati sinonime. CharFilter - mijenja cijeli izvorni niz, na primjer, izrezuje html oznake.
Hajde da iskoristimo prednost api i da vidimo kako standardni i ruski analizatori transformiraju niz "Smiješne priče o mačićima":
# используем анализатор standard
# обязательно нужно перекодировать не ASCII символы
curl -XGET "$ES_URL/_analyze?pretty&analyzer=standard&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
Standardni analizator je podijelio string po razmacima i konvertirao sve u mala slova, ruski analizator je uklonio nevažne riječi, pretvorio ga u mala slova i ostavio korijen riječi.
Hajde da vidimo koje Tokenizer, TokenFilters, CharFilters ruski analizator koristi:
Hajde da opišemo naš analizator baziran na ruskom jeziku, koji će izrezati html oznake. Nazovimo to zadanim, jer analizator sa ovim imenom će se koristiti po defaultu.
Prvo će se sve HTML oznake ukloniti iz izvornog niza, zatim će ga standard za tokenizer podijeliti na tokene, rezultirajući tokeni će se premjestiti na mala slova, beznačajne riječi će biti uklonjene, a preostali tokeni će ostati osnova riječi.
Kreiranje indeksa
Iznad smo opisali zadani analizator. Primjenjivat će se na sva polja stringova. Naš post sadrži niz oznaka, tako da će i tagovi biti obrađeni od strane analizatora. Jer Tražimo postove po tačnom podudaranju sa oznakom, zatim moramo onemogućiti analizu za polje oznaka.
Kreirajmo indeksni blog2 sa analizatorom i mapiranjem, u kojem je onemogućena analiza polja oznaka:
Dodajmo ista 3 posta u ovaj indeks (blog2). Izostaviću ovaj proces jer... slično je dodavanju dokumenata u indeks bloga.
Pretraživanje cijelog teksta s podrškom za izraze
Pogledajmo drugu vrstu zahtjeva:
# найдем документы, в которых встречается слово 'истории'
# query -> simple_query_string -> query содержит поисковый запрос
# поле title имеет приоритет 3
# поле tags имеет приоритет 2
# поле content имеет приоритет 1
# приоритет используется при ранжировании результатов
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "истории",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
Jer Koristimo analizator sa ruskim poreklom, onda će ovaj zahtev vratiti sve dokumente, iako sadrže samo reč 'istorija'.
Zahtjev može sadržavati posebne znakove, na primjer:
""fried eggs" +(eggplant | potato) -frittata"
Sintaksa zahtjeva:
+ signifies AND operation
| signifies OR operation
- negates a single token
" wraps a number of tokens to signify a phrase for searching
* at the end of a term signifies a prefix query
( and ) signify precedence
~N after a word signifies edit distance (fuzziness)
~N after a phrase signifies slop amount
# найдем документы без слова 'щенки'
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "-щенки",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
# получим 2 поста про котиков
Ako ste zainteresovani za slične članke-lekcije, imate ideje za nove članke, ili imate predloge za saradnju, biće mi drago da dobijete poruku u ličnoj poruci ili na email [email zaštićen].