Hei venner! Det er folk med forskjellige nivåer av erfaring som bidrar til forumet vårt - og det er flott! Men akkurat nå leter jeg etter ekte Ruby-titaner!
Elasticsearch er en søkemotor som er basert på et pålitelig og modent bibliotek - Apache Lucene. Stor aktivitet i git prosjekt repository and the implementation in such projects as GitHub, SoundCloud, Stack Overflow and LinkedIn bear testimony to its great popularity. The part “Elastic” says it all about the nature of the system, whose capabilities are enormous: from a simple file search on a small scale, through knowledge discovery, to big data analysis in real time.What makes Elastic a more powerful than the competition is the set of default configurations and behaviors, which allow to create a cluster and start adding documents to the index in a couple of minutes. Elastic will configure a cluster for you, will define an index and define the types of fields for the first document obtained, and when you add another server, it will automatically deal with dividing index data between servers.Unfortunately, the above mentioned automation makes it unclear to us what the default settings implicate, and it often turns out to be misleading. This article starts a series where I will be dealing with the most popular gotchas, which you might encounter during the process of Elastic-based app creation.
Antall skjær kan ikke endres
La oss indeksere det første dokumentet ved hjelp av indeks API:
$ curl -XPUT 'http://localhost:9200/myindex/employee/1' -d '{
"fornavn" : "Jane",
"etternavn" : "Smith",
"steet_number": 12
}'
I dette øyeblikket oppretter Elastic en indeks for oss, med tittelen myindex. Det som ikke er synlig her, er antallet shards som er tilordnet indeksen. Shards kan forstås som individuelle prosesser som er ansvarlige for indeksering, lagring og søk i en del av dokumentene i en hel indeks. Under prosessen med dokumentindeksering bestemmer elastic i hvilken shard et dokument skal finnes. Det er basert på følgende formel:
shard = hash(document_id) % number_of_primary_shards
Det er nå klart at antallet primære skjæringer ikke kan endres for en indeks som inneholder dokumenter. Før du indekserer det første dokumentet, må du derfor alltid opprette en indeks manuelt, og angi det antallet skår som du mener er tilstrekkelig for en mengde indekserte data:
$ curl -XPUT 'http://localhost:9200/myindex/' -d '{
"innstillinger" : {
"antall_av_skår" : 10
}
}'
Standardverdi for antall_av_skår er 5. Dette betyr at indeksen kan skaleres til opptil 5 servere, som samler inn data under indekseringen. For produksjonsmiljøet bør verdien av shards settes avhengig av forventet indekseringsfrekvens og størrelsen på dokumentene. For utviklings- og testmiljøer anbefaler jeg å sette verdien til 1 - hvorfor det? Det vil bli forklart i neste avsnitt i denne artikkelen.
Sortering av tekstsøkeresultater med et relativt lite antall dokumenter
Når vi søker etter et dokument med en frase:
$ curl -XGET 'http://localhost:9200/myindex/my_type/_search' -d
'{
"query": {
"match": {
"title": "Den raske, brune reven"
}
}
}'
Elastic behandler tekstsøk i få trinn, enkelt sagt:
- frasen fra forespørselen konverteres til samme identiske form som dokumentet ble indeksert i, i vårt tilfelle vil det være et sett med termer:
["rask", "brun", "rev"] ("den" er fjernet fordi det er ubetydelig),
- indeksen blir gjennomgått for å søke i dokumenter som inneholder minst ett av søkeordene,
- hvert dokument som er et treff, blir evaluert med tanke på om det er relevant for søkefrasen,
- sorteres resultatene etter den beregnede relevansen, og den første siden med resultater returneres til brukeren.
I det tredje trinnet tas det blant annet hensyn til følgende verdier:
- hvor mange ord fra søkefrasen som finnes i dokumentet
- hvor ofte et gitt ord forekommer i et dokument (TF - termfrekvens)
- om og hvor ofte de samsvarende ordene forekommer i andre dokumenter (IDF - invers dokumentfrekvens) - jo mer populært ordet er i andre dokumenter, desto mindre viktig er det
- hvor langt er dokumentet
Funksjonen til IDF er viktig for oss. Elastic beregner av ytelseshensyn ikke denne verdien for hvert dokument i indeksen - i stedet beregner hver shard (indeksarbeider) sin lokale IDF og bruker den til sortering. Derfor kan vi under indekssøk med et lavt antall dokumenter få svært forskjellige resultater, avhengig av antall skjæringer i en indeks og dokumentfordelingen.
La oss tenke oss at vi har to skjæringer i en indeks; i den første er det 8 dokumenter indeksert med ordet "fox", og i den andre er det bare 2 dokumenter med det samme ordet. Som et resultat vil ordet "fox" være svært forskjellig i de to skårene, og dette kan gi feil resultater. Derfor bør det opprettes en indeks som bare består av én primær del for utviklingsformål:
$ curl -XPUT 'http://localhost:9200/myindex/' -d
'{"settings" : { "number_of_shards" : 1 } }' }'
Visning av resultatene fra "fjerne" søkesider dreper klyngen din
Som jeg har skrevet i tidligere avsnitt, deles dokumentene i en indeks mellom helt individuelle indeksprosesser - shards. Hver prosess er helt uavhengig og behandler bare de dokumentene som er tilordnet den.
Når vi søker i en indeks med millioner av dokumenter og venter på å få de 10 beste resultatene, må hver klynge returnere sine 10 best matchende resultater til klyngens node, som startet søket. Deretter slås svarene fra hver del sammen, og de 10 beste søkeresultatene velges (innenfor hele indeksen). En slik tilnærming gjør det mulig å distribuere søkeprosessen effektivt mellom mange servere.
La oss tenke oss at appen vår tillater visning av 50 resultater per side, uten begrensninger når det gjelder antall sider som kan vises av en bruker. Husk at indeksen vår består av 10 primære skjæringer (1 per server).
La oss se hvordan anskaffelsen av søkeresultater vil se ut for den første og den 100. siden:
Side nr. 1 av søkeresultatene:
- Noden som mottar en forespørsel (kontrolleren), sender den videre til 10 skjæringer.
- Hver del returnerer sine 50 best matchende dokumenter sortert etter relevans.
- Etter at svarene er mottatt fra hver del, slår kontrolleren sammen resultatene (500 dokumenter).
- Resultatene våre er de 50 beste dokumentene fra forrige trinn.
Side nr. 100 av søkeresultatene:
- Noden som mottar en forespørsel (kontrolleren), sender den videre til 10 skjæringer.
- Hver del returnerer sine 5000 best matchende dokumenter sortert etter relevans.
- Etter å ha mottatt svar fra hver delingsenhet, slår kontrolleren sammen resultatene (50000 dokumenter).
- Resultatene våre er dokumentene fra forrige trinn, plassert 4901 - 5000.
Hvis vi antar at et dokument er 1 KB stort, betyr det i det andre tilfellet at ca. 50 MB data må sendes og behandles rundt i klyngen for å vise 100 resultater for én bruker.
Det er ikke vanskelig å legge merke til at nettverkstrafikken og indeksbelastningen øker betydelig for hver påfølgende resultatside. Derfor anbefales det ikke å gjøre de "fjerne" søkesidene tilgjengelige for brukeren. Hvis indeksen vår er godt konfigurert, bør brukeren finne resultatet han er interessert i på de første søkesidene, og vi vil beskytte oss mot unødvendig belastning av klyngen vår. For å bevise denne regelen kan du sjekke hvor mange søkeresultatsider de mest populære søkemotorene på nettet tillater visning av.
Det som også er interessant, er observasjonen av nettleserens responstid for påfølgende søkeresultatsider. Nedenfor finner du for eksempel svartider for individuelle søkeresultatsider i Google Søk (søkeordet var "søkemotor"):
| Søkeresultatside (10 dokumenter per side) | Svartid | Svartid
|——————————————–|—————|
1 | 250ms | 1 | 250ms
| 10 | 290ms | | | 10
| 20 | 350ms | | 20
| 30 | 380ms | | 30
| 38 (siste tilgjengelige)
I neste del vil jeg se nærmere på problemene knyttet til dokumentindeksering.