Elasticsearch er en søkemotor med json rest api, som bruker Lucene og skrevet i Java. En beskrivelse av alle fordelene med denne motoren er tilgjengelig på offisiell nettside. I det følgende vil vi referere til Elasticsearch som ES.
Lignende motorer brukes for komplekse søk i en dokumentdatabase. For eksempel søk som tar hensyn til språkets morfologi eller søk etter geokoordinater.
I denne artikkelen vil jeg snakke om det grunnleggende om ES ved å bruke eksemplet med å indeksere blogginnlegg. Jeg skal vise deg hvordan du filtrerer, sorterer og søker i dokumenter.
For ikke å være avhengig av operativsystemet, vil jeg sende alle forespørsler til ES ved å bruke CURL. Det er også en plugin for google chrome som heter forstand.
Teksten inneholder lenker til dokumentasjon og andre kilder. På slutten er det lenker for rask tilgang til dokumentasjonen. Definisjoner av ukjente termer finner du i ordlister.
Installerer ES
For å gjøre dette trenger vi først Java. Utviklere anbefale installer Java-versjoner nyere enn Java 8-oppdatering 20 eller Java 7-oppdatering 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 opprettet automatisk index blogg og typen post. Vi kan tegne en betinget analogi: en indeks er en database, og en type er en tabell i denne databasen. Hver type har sitt eget skjema − kartlegging, akkurat som en relasjonstabell. Kartlegging genereres automatisk når dokumentet er indeksert:
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"
I serversvaret la jeg til verdiene til feltene i det indekserte dokumentet i kommentarene:
Det er verdt å merke seg at ES ikke skiller mellom en enkelt verdi og en rekke verdier. For eksempel inneholder tittelfeltet ganske enkelt en tittel, og tags-feltet inneholder en rekke strenger, selv om de er representert på samme måte i kartlegging.
Vi snakker mer om kartlegging senere.
forespørsler
Henter et dokument etter dets id:
# извлечем документ с id 1 типа post из индекса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
Nye nøkler dukket opp i svaret: _version и _source. Generelt er alle nøkler som starter med _ er klassifisert som offisielle.
Ключ _version viser dokumentversjonen. Det er nødvendig for at den optimistiske låsemekanismen skal fungere. For eksempel ønsker vi å endre et dokument som har versjon 1. Vi sender inn det endrede dokumentet og indikerer at dette er en redigering av et dokument med versjon 1. Hvis noen andre også har redigert et dokument med versjon 1 og sendt inn endringer før oss, så ES vil ikke godta våre endringer, fordi den lagrer dokumentet med versjon 2.
Ключ _source inneholder dokumentet som vi indekserte. ES bruker ikke denne verdien for søkeoperasjoner fordi Indekser brukes til å søke. For å spare plass lagrer ES et komprimert kildedokument. Hvis vi bare trenger id, og ikke hele kildedokumentet, kan vi deaktivere kildelagring.
Hvis vi ikke trenger ytterligere informasjon, kan vi kun få innholdet i _source:
curl -XPUT "$ES_URL/blog/post/3" -d'
{
"title": "Как у меня появился котенок",
"content": "<p>Душераздирающая история про бедного котенка с улицы<p>",
"tags": [
"котята"
],
"published_at": "2014-07-21T20:44:42+00:00"
}'
Сортировка
# найдем последний пост по дате публикации и извлечем поля title и published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"size": 1,
"_source": ["title", "published_at"],
"sort": [{"published_at": "desc"}]
}'
Vi valgte det siste innlegget. size begrenser antall dokumenter som skal utstedes. total viser det totale antallet dokumenter som samsvarer med forespørselen. sort i utdataene inneholder en rekke heltall som sorteringen utføres med. De. datoen ble konvertert til et heltall. Mer informasjon om sortering finner du i dokumentasjon.
Filtre og spørringer
ES siden versjon 2 ikke skiller mellom filtre og spørringer, i stedet begrepet kontekster introduseres.
En spørringskontekst skiller seg fra en filterkontekst ved at spørringen genererer en _score og ikke bufres. Jeg skal vise deg hva _score er senere.
Filtrer etter dato
Vi bruker forespørselen område i sammenheng med filter:
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'
Filtrer etter tagger
Vi bruker term spørring for å søke etter dokument-ID-er som inneholder et gitt ord:
# найдем все документы, в поле tags которых есть элемент 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": [
"title",
"tags"
],
"filter": {
"term": {
"tags": "котята"
}
}
}'
Men hvis vi søker etter "historier" i innholdsfeltet, vil vi ikke finne noe, fordi Indeksen inneholder bare de originale ordene, ikke stammene deres. For å gjøre et søk av høy kvalitet, må du konfigurere analysatoren.
Feltet _score viser relevans. Hvis forespørselen utføres i en filterkontekst, vil _score-verdien alltid være lik 1, noe som betyr et fullstendig samsvar med filteret.
Analysatorer
Analysatorer er nødvendig for å konvertere kildeteksten til et sett med tokens.
Analysatorer består av en Tokenizer og flere valgfrie TokenFilters. Tokenizer kan innledes med flere CharFilters. Tokenizere deler opp kildestrengen i tokens, for eksempel mellomrom og tegnsettingstegn. TokenFilter kan endre tokens, slette eller legge til nye, for eksempel la bare stammen til ordet stå, fjerne preposisjoner, legge til synonymer. CharFilter - endrer hele kildestrengen, for eksempel, kutter ut html-tagger.
La oss dra nytte api og la oss se hvordan de standard og russiske analysatorene forvandler strengen "Morsomme historier om kattunger":
# используем анализатор 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"
Standardanalysatoren delte opp strengen i mellomrom og konverterte alt til små bokstaver, den russiske analysatoren fjernet uviktige ord, konverterte den til små bokstaver og forlot stammen til ordene.
La oss se hvilke Tokenizer, TokenFilters, CharFilters den russiske analysatoren bruker:
La oss beskrive analysatoren vår basert på russisk, som vil kutte ut html-koder. La oss kalle det standard, fordi en analysator med dette navnet vil bli brukt som standard.
Først vil alle HTML-tagger fjernes fra kildestrengen, deretter vil tokenizer-standarden dele den opp i tokens, de resulterende tokenene vil flytte til små bokstaver, ubetydelige ord vil bli fjernet, og de gjenværende tokens vil forbli stammen til ordet.
Opprette en indeks
Ovenfor beskrev vi standardanalysatoren. Det vil gjelde for alle strengfelt. Innlegget vårt inneholder en rekke tagger, så taggene vil også bli behandlet av analysatoren. Fordi Vi ser etter innlegg etter nøyaktig samsvar med en tag, så må vi deaktivere analyse for tags-feltet.
La oss lage en indeksblogg2 med en analysator og kartlegging, der analysen av taggerfeltet er deaktivert:
La oss legge til de samme 3 innleggene til denne indeksen (blogg2). Jeg vil utelate denne prosessen fordi... det ligner på å legge til dokumenter i bloggindeksen.
Fulltekstsøk med uttrykksstøtte
La oss ta en titt på en annen type forespørsel:
# найдем документы, в которых встречается слово 'истории'
# 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"
]
}
}
}'
Fordi Vi bruker en analysator med russisk stemming, så vil denne forespørselen returnere alle dokumenter, selv om de bare inneholder ordet "historie".
Forespørselen kan inneholde spesialtegn, for eksempel:
""fried eggs" +(eggplant | potato) -frittata"
Forespørselssyntaks:
+ 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 поста про котиков
Hvis du er interessert i lignende artikler-leksjoner, har ideer til nye artikler, eller har forslag til samarbeid, vil jeg gjerne motta en melding i en personlig melding eller på e-post [e-postbeskyttet].