Elasticsearch upiti s proljetnim podacima

1. Uvod

U prethodnom članku pokazali smo kako konfigurirati i koristiti Spring Data Elasticsearch za projekt. U ovom ćemo članku ispitati nekoliko vrsta upita koje nudi Elasticsearch, a također ćemo razgovarati o analizatorima polja i njihovom utjecaju na rezultate pretraživanja.

2. Analizatori

Sva pohranjena polja niza prema zadanim postavkama obrađuju analizator. Analizator se sastoji od jednog tokenizera i nekoliko filtera tokena, a obično mu prethodi jedan ili više filtera znakova.

Zadani analizator dijeli niz uobičajenim odvajačima riječi (poput razmaka ili interpunkcije) i stavlja svaki token malim slovima. Također zanemaruje uobičajene engleske riječi.

Elasticsearch se također može konfigurirati da se polje istovremeno analizira i ne analizira.

Na primjer, u Članak razreda, pretpostavimo da polje naslova pohranimo kao standardno analizirano polje. Isto polje sa sufiksom doslovno pohranit će se kao neanalizirano polje:

@MultiField (mainField = @Field (type = Text, fielddata = true), otherFields = {@InnerField (sufiks = "verbatim", type = Keyword)}) naslov privatnog niza;

Ovdje primjenjujemo @MultiField napomena kako bi Spring Data-u rekli da bismo željeli da se ovo polje indeksira na nekoliko načina. U glavnom polju koristit će se naziv titula i analizirat će se prema gore opisanim pravilima.

Ali pružamo i drugu napomenu, @InnerField, koji opisuje dodatno indeksiranje titula polje. Koristimo FieldType.keyword da naznačimo da ne želimo koristiti analizator prilikom izvođenja dodatnog indeksiranja polja i da bi ovu vrijednost trebalo pohraniti pomoću ugniježđenog polja sa sufiksom doslovno.

2.1. Analizirana polja

Pogledajmo primjer. Pretpostavimo da je u naš indeks dodan članak s naslovom "Spring Data Elasticsearch". Zadani analizator razbit će niz na razmake i stvoriti male znakove: “Proljeće“, “podaci", i "elastično pretraživanje“.

Sada možemo upotrijebiti bilo koju kombinaciju ovih izraza kako bismo se podudarali s dokumentom:

NativeSearchQuery searchQuery = novi NativeSearchQueryBuilder () .withQuery (matchQuery ("naslov", "podaci elastičnog pretraživanja")) .build ();

2.2. Neanalizirana polja

Neanalizirano polje nije tokenizirano, pa se može podudarati u cjelini samo kada se koriste upiti za podudaranje ili pojam:

NativeSearchQuery searchQuery = novo NativeSearchQueryBuilder () .withQuery (matchQuery ("title.verbatim", "Drugi članak o Elasticsearch")) .build ();

Pomoću upita za podudaranje možemo pretraživati ​​samo puni naslov, koji također razlikuje velika i mala slova.

3. Upit za podudaranje

A upit za podudaranje prihvaća tekst, brojeve i datume.

Postoje tri vrste upita za "podudaranje":

  • boolean
  • fraza i
  • prefiks_fraze

U ovom ćemo dijelu istražiti boolean upit za podudaranje.

3.1. Podudaranje s logičkim operatorima

boolean je zadana vrsta upita za podudaranje; možete odrediti koji će logički operator koristiti (ili je zadana vrijednost):

NativeSearchQuery searchQuery = novo NativeSearchQueryBuilder () .withQuery (matchQuery ("naslov", "Tražilice"). Operator (Operator.AND)) .build (); Članci SearchHits = elasticsearchTemplate () .search (searchQuery, Article.class, IndexCoordinates.of ("blog"));

Ovaj upit vraća članak s naslovom "Tražilice" navodeći dva pojma iz naslova sa i operater. Ali što će se dogoditi ako pretražujemo sa zadanim (ili) operator kada se podudara samo jedan od pojmova?

NativeSearchQuery searchQuery = novo NativeSearchQueryBuilder () .withQuery (matchQuery ("title", "Engines Solutions")) .build (); Članci SearchHits = elasticsearchTemplate () .search (searchQuery, Article.class, IndexCoordinate.of ("blog")); assertEquals (1, articles.getTotalHits ()); assertEquals ("Tražilice", articles.getSearchHit (0) .getContent (). getTitle ());

"Tražilice”Članak se i dalje podudara, ali imat će nižu ocjenu jer se ne podudaraju svi pojmovi.

Zbir bodova svakog podudarnog pojma zbraja se s ukupnim rezultatom svakog rezultirajućeg dokumenta.

Mogu biti situacije u kojima će dokument koji sadrži rijedak pojam upisan u upit imati viši rang od dokumenta koji sadrži nekoliko uobičajenih izraza.

3.2. Nejasnoće

Kada korisnik natipka riječ u riječi, još uvijek je moguće upariti je s pretragom tako što ćete navesti nejasnoća parametar, koji omogućuje netočno podudaranje.

Za polja niza, nejasnoća znači udaljenost uređivanja: broj promjena od jednog znaka koje je potrebno izvršiti u jednom nizu da bi bio isti kao drugi niz.

NativeSearchQuery searchQuery = novo NativeSearchQueryBuilder () .withQuery (matchQuery ("title", "spring date elasticsearch") .operator (Operator.AND) .fuzziness (Fuzziness.ONE) .prefixLength (3)) .build ();

The dužina prefiksa parametar koristi se za poboljšanje performansi. U ovom slučaju zahtijevamo da se prva tri znaka točno podudaraju, što smanjuje broj mogućih kombinacija.

5. Pretraživanje fraza

Fazno pretraživanje je strože, iako ga možete kontrolirati pomoću aljkavost parametar. Ovaj parametar govori upit fraze koliko su dopušteni međusobno razdvojeni pojmovi dok dokument još uvijek podudara.

Drugim riječima, predstavlja koliko puta trebate premjestiti pojam kako bi se upit i dokument podudarali:

NativeSearchQuery searchQuery = novo NativeSearchQueryBuilder () .withQuery (matchPhraseQuery ("title", "spring elasticsearch"). Slop (1)) .build ();

Ovdje će upit odgovarati dokumentu s naslovom “Spring Data Elasticsearch”Jer smo postavili nagib na jedan.

6. Upit s više podudaranja

Kada želite pretraživati ​​u više polja, onda biste mogli koristiti QueryBuilders # multiMatchQuery () gdje odredite sva polja koja se podudaraju:

NativeSearchQuery searchQuery = novo NativeSearchQueryBuilder () .withQuery (multiMatchQuery ("tutorial") .field ("title") .field ("tags") .type (MultiMatchQueryBuilder.Type.BEST_FIELDS)) .build ();

Ovdje pretražujemo titula i oznake polja za šibicu.

Primijetite da ovdje koristimo strategiju bodovanja "najbolja polja". Bit će potreban maksimalan rezultat među poljima kao rezultat dokumenta.

7. Zbirke

U našem Članak razred također smo definirali a oznake polje, koje se ne analizira. Pomoću agregacije lako bismo mogli stvoriti oblak oznaka.

Imajte na umu da, jer se polje ne analizira, oznake neće biti tokenizirane:

TermsAggregationBuilder aggregation = AggregationBuilders.terms ("top_tags") .field ("tags") .order (Terms.Order.count (false)); SearchSourceBuilder builder = novi SearchSourceBuilder (). Agregacija (agregacija); SearchRequest searchRequest = novi SearchRequest (). Indeksi ("blog"). Vrste ("članak"). Izvor (graditelj); SearchResponse response = client.search (searchRequest, RequestOptions.DEFAULT); Rezultati mape = response.getAggregations (). AsMap (); StringTerms topTags = (StringTerms) results.get ("top_tags"); Ključevi popisa = topTags.getBuckets () .stream () .map (b -> b.getKeyAsString ()) .collect (toList ()); assertEquals (asList ("elasticsearch", "spring data", "search engine", "tutorial"), tipke);

8. Sažetak

U ovom smo članku razgovarali o razlici između analiziranih i neanaliziranih polja te kako ta razlika utječe na pretraživanje.

Također smo saznali o nekoliko vrsta upita koje pruža Elasticsearch, poput upita za podudaranje, upita za podudaranje fraze, upita za pretraživanje cijelog teksta i logičkog upita.

Elasticsearch nudi mnoge druge vrste upita, poput geo upita, upita skripti i složenih upita. O njima možete pročitati u dokumentaciji Elasticsearch i istražiti Spring Data Elasticsearch API kako biste koristili ove upite u svom kodu.

Projekt koji sadrži primjere iz ovog članka možete pronaći u spremištu GitHub.