Elasticsearch je vyhľadávací nástroj s json rest api, ktorý používa Lucene a je napísaný v jazyku Java. Popis všetkých výhod tohto motora je dostupný na oficiálne internetové stránky. V nasledujúcom texte budeme označovať Elasticsearch ako ES.
Podobné nástroje sa používajú na komplexné vyhľadávanie v databáze dokumentov. Napríklad vyhľadávanie s prihliadnutím na morfológiu jazyka alebo vyhľadávanie podľa geo súradníc.
V tomto článku budem hovoriť o základoch ES na príklade indexovania blogových príspevkov. Ukážem vám, ako dokumenty filtrovať, triediť a vyhľadávať.
Aby som nebol závislý od operačného systému, urobím všetky požiadavky na ES pomocou CURL. Existuje aj plugin pre google chrome tzv význam.
Text obsahuje odkazy na dokumentáciu a iné zdroje. Na konci sú odkazy na rýchly prístup k dokumentácii. Definície neznámych pojmov nájdete v glosáre.
Inštalácia ES
Na to potrebujeme najprv Javu. Vývojári odporučiť nainštalujte verzie Java novšie ako Java 8 update 20 alebo Java 7 update 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 automaticky vytvorené index blog a тип príspevok. Môžeme nakresliť podmienenú analógiu: index je databáza a typ je tabuľka v tejto databáze. Každý typ má svoju vlastnú schému − mapovanie, rovnako ako relačná tabuľka. Mapovanie sa generuje automaticky pri indexovaní dokumentu:
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"
V odpovedi servera som do komentárov pridal hodnoty polí indexovaného dokumentu:
Stojí za zmienku, že ES nerozlišuje medzi jednou hodnotou a súborom hodnôt. Napríklad pole title jednoducho obsahuje názov a pole tagy obsahuje pole reťazcov, hoci sú v mapovaní reprezentované rovnakým spôsobom.
O mapovaní si povieme viac neskôr.
žiadosti
Načítanie dokumentu podľa jeho ID:
# извлечем документ с id 1 типа post из индекса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
V odpovedi sa objavili nové kľúče: _version и _source. Vo všeobecnosti všetky kľúče začínajúce na _ sú klasifikované ako oficiálne.
kľúč _version zobrazuje verziu dokumentu. Je to potrebné pre fungovanie optimistického uzamykacieho mechanizmu. Napríklad chceme zmeniť dokument, ktorý má verziu 1. Odošleme zmenený dokument a uvedieme, že ide o úpravu dokumentu s verziou 1. Ak niekto iný upravoval aj dokument s verziou 1 a odoslal zmeny pred nami, potom ES neprijme naše zmeny, pretože ukladá dokument s verziou 2.
kľúč _source obsahuje dokument, ktorý sme indexovali. ES nepoužíva túto hodnotu na operácie vyhľadávania, pretože Na vyhľadávanie sa používajú indexy. Aby sa ušetrilo miesto, ES ukladá komprimovaný zdrojový dokument. Ak potrebujeme iba ID a nie celý zdrojový dokument, môžeme zakázať ukladanie zdroja.
Ak nepotrebujeme ďalšie informácie, môžeme získať iba obsah _source:
curl -XPUT "$ES_URL/blog/post/3" -d'
{
"title": "Как у меня появился котенок",
"content": "<p>Душераздирающая история про бедного котенка с улицы<p>",
"tags": [
"котята"
],
"published_at": "2014-07-21T20:44:42+00:00"
}'
triedenie
# найдем последний пост по дате публикации и извлечем поля title и published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"size": 1,
"_source": ["title", "published_at"],
"sort": [{"published_at": "desc"}]
}'
Vybrali sme posledný príspevok. size obmedzuje počet dokumentov, ktoré sa majú vydať. total zobrazuje celkový počet dokumentov zodpovedajúcich požiadavke. sort vo výstupe obsahuje pole celých čísel, podľa ktorých sa vykonáva triedenie. Tie. dátum bol prevedený na celé číslo. Viac informácií o triedení nájdete v dokumentáciu.
Filtre a dotazy
ES od verzie 2 nerozlišuje medzi filtrami a dopytmi zavádza sa pojem kontextov.
Kontext dotazu sa líši od kontextu filtra v tom, že dotaz generuje _score a neukladá sa do vyrovnávacej pamäte. Čo je _skóre, vám ukážem neskôr.
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'
Filtrujte podľa značiek
Používame termínový dotaz ak chcete vyhľadať ID dokumentov obsahujúce dané slovo:
# найдем все документы, в поле tags которых есть элемент 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": [
"title",
"tags"
],
"filter": {
"term": {
"tags": "котята"
}
}
}'
Ak však hľadáme „príbehy“ v poli obsahu, nenájdeme nič, pretože Index obsahuje iba pôvodné slová, nie ich kmene. Ak chcete vykonať vysokokvalitné vyhľadávanie, musíte nakonfigurovať analyzátor.
Pole _score relácie relevantnosť. Ak sa požiadavka vykoná v kontexte filtra, potom sa hodnota _score bude vždy rovnať 1, čo znamená úplnú zhodu s filtrom.
analyzátory
analyzátory sú potrebné na konverziu zdrojového textu na sadu tokenov.
Analyzátory pozostávajú z jedného Tokenizer a niekoľko voliteľných TokenFilters. Tokenizeru môže predchádzať niekoľko CharFilters. Tokenizéry rozdeľujú zdrojový reťazec na tokeny, ako sú medzery a interpunkčné znamienka. TokenFilter dokáže meniť tokeny, mazať alebo pridávať nové, napríklad ponechať len kmeň slova, odstraňovať predložky, pridávať synonymá. CharFilter - zmení celý zdrojový reťazec, napríklad vystrihne html značky.
Využime to api a pozrime sa, ako štandardné a ruské analyzátory transformujú reťazec „Vtipné príbehy o mačiatkach“:
# используем анализатор 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"
Štandardný analyzátor rozdelil reťazec podľa medzier a všetko skonvertoval na malé písmená, ruský analyzátor odstránil nedôležité slová, skonvertoval ho na malé písmená a nechal kmeň slov.
Pozrime sa, ktorý Tokenizer, TokenFilters, CharFilters používa ruský analyzátor:
Poďme si popísať náš analyzátor založený na ruštine, ktorý vystrihne html tagy. Nazvime to predvolené, pretože predvolene sa použije analyzátor s týmto názvom.
Najprv sa zo zdrojového reťazca odstránia všetky značky HTML, potom ho štandard tokenizéra rozdelí na tokeny, výsledné tokeny sa presunú na malé písmená, nepodstatné slová sa odstránia a zvyšné tokeny zostanú kmeňom slova.
Vytvorenie indexu
Vyššie sme opísali predvolený analyzátor. Bude sa vzťahovať na všetky polia reťazcov. Náš príspevok obsahuje pole značiek, takže značky spracuje aj analyzátor. Pretože Hľadáme príspevky podľa presnej zhody so značkou, potom musíme zakázať analýzu poľa značiek.
Vytvorme index blog2 s analyzátorom a mapovaním, v ktorom je zakázaná analýza poľa značiek:
Do tohto indexu (blog3) pridáme rovnaké 2 príspevky. Tento proces vynechám, pretože... je to podobné ako pridávanie dokumentov do indexu blogu.
Fulltextové vyhľadávanie s podporou výrazov
Pozrime sa na iný typ žiadosti:
# найдем документы, в которых встречается слово 'истории'
# 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"
]
}
}
}'
Pretože Používame analyzátor s ruským pôvodom, potom táto žiadosť vráti všetky dokumenty, hoci obsahujú iba slovo „história“.
Žiadosť môže obsahovať špeciálne znaky, napr.
""fried eggs" +(eggplant | potato) -frittata"
Syntax požiadavky:
+ 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 поста про котиков
Ak máte záujem o podobné články-lekcie, nápady na nové články alebo návrhy na spoluprácu, budem rád, ak mi pošlete správu v osobnej správe alebo emailom [chránené e-mailom].