Jednostavna provedba označavanja s Elasticsearch

Vrh postojanosti

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ Ovaj je članak dio serije: • Jednostavna provedba označavanja s Elasticsearch (trenutni članak) • Jednostavna provedba označavanja s JPA

• Napredna implementacija označavanja s JPA

• Jednostavna implementacija označavanja s MongoDB-om

1. Pregled

Označavanje je uobičajeni obrazac dizajna koji nam omogućuje kategorizaciju i filtriranje stavki u našem podatkovnom modelu.

U ovom ćemo članku implementirati označavanje pomoću Springa i Elasticsearch-a. Koristit ćemo i Spring Data i Elasticsearch API.

Prije svega, nećemo pokrivati ​​osnove dobivanja Elasticsearch i Spring Data - možete ih istražiti ovdje.

2. Dodavanje oznaka

Najjednostavnija implementacija označavanja je niz nizova. To možemo implementirati dodavanjem novog polja u naš model podataka poput ovog:

@Document (indexName = "blog", type = "article") javna klasa Article {// ... @Field (type = Keyword) private String [] tagovi; // ...}

Primijetite upotrebu Ključna riječ tip polja. Želimo samo točno podudaranje naših oznaka da bismo filtrirali rezultat. To nam omogućuje upotrebu sličnih, ali odvojenih oznaka poput elasticsearchIsAwesome i elasticsearchIsTerrible.

Analizirana polja vratila bi djelomične pogotke što je u ovom slučaju pogrešno ponašanje.

3. Izgradnja upita

Oznake nam omogućuju manipuliranje našim upitima na zanimljive načine. Možemo pretraživati ​​preko njih kao bilo koje drugo polje ili ih koristiti za filtriranje rezultata match_all upiti. Također ih možemo koristiti s drugim upitima kako bismo pooštrili svoje rezultate.

3.1. Traženje oznaka

Novi označiti polje koje smo kreirali na našem modelu je baš kao i svako drugo polje u našem indeksu. Možemo pretraživati ​​bilo koji entitet koji ima određenu oznaku poput ove:

@Query ("{\" bool \ ": {\" must \ ": [{\" match \ ": {\" tags \ ": \"? 0 \ "}}]}}") Stranica findByTagUsingDeclaredQuery (Niz oznaka, Pageable pageable);

Ovaj primjer koristi Spring Data Repozitorij za konstrukciju našeg upita, ali jednako brzo možemo koristiti Predložak za odmor kako bismo ručno postavili upit za klaster Elasticsearch.

Slično tome, možemo koristiti API Elasticsearch:

boolQuery (). must (termQuery ("oznake", "elastično pretraživanje"));

Pretpostavimo da u našem indeksu koristimo sljedeće dokumente:

[{"id": 1, "title": "Spring Data Elasticsearch", "author": [{"name": "John Doe"}, {"name": "John Smith"}], "tags": ["elasticsearch", "spring data"]}, {"id": 2, "title": "Tražilice", "author": [{"name": "John Doe"}], "tags": [ "pretraživači", "tutorial"]}, {"id": 3, "title": "Drugi članak o Elasticsearchu", "autori": [{"name": "John Smith"}], "tags": ["elasticsearch", "spring data"]}, {"id": 4, "title": "Elasticsearch Tutorial", "author": [{"name": "John Doe"}], "tags": [ "elastično pretraživanje"]},]

Sada možemo koristiti ovaj upit:

Article articleByTags = articleService.findByTagUsingDeclaredQuery ("elasticsearch", PageRequest.of (0, 10)); // articleByTags sadržavat će 3 članka [1, 3, 4] assertThat (articleByTags, containsInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (3)), hasProperty ("id", je (4))));

3.2. Filtriranje svih dokumenata

Uobičajeni obrazac dizajna je stvaranje a Prikaz filtriranog popisa u korisničkom sučelju koji prikazuje sve entitete, ali također omogućuje korisniku filtriranje na temelju različitih kriterija.

Recimo da želimo vratiti sve članke filtrirane prema bilo kojoj oznaci koju korisnik odabere:

@Query ("{\" bool \ ": {\" must \ ":" + "{\" match_all \ ": {}}, \" filter \ ": {\" term \ ": {\" tagovi \ ": \"? 0 \ "}}}}") Stranica findByFilteredTagQuery (Oznaka niza, dostupna na stranici);

Još jednom, koristimo Spring Data za izradu našeg deklariranog upita.

Slijedom toga, upit koji koristimo podijeljen je u dva dijela. Upit za bodovanje prvi je pojam, u ovom slučaju, match_all. Upit za filtriranje je sljedeći i Elasticsearchu govori koje rezultate treba odbaciti.

Evo kako koristimo ovaj upit:

Page articleByTags = articleService.findByFilteredTagQuery ("elasticsearch", PageRequest.of (0, 10)); // articleByTags sadržavat će 3 članka [1, 3, 4] assertThat (articleByTags, containsInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (3)), hasProperty ("id", je (4))));

Važno je shvatiti da, iako ovo daje iste rezultate kao i naš gornji primjer, ovaj će upit imati bolju izvedbu.

3.3. Filtriranje upita

Ponekad pretraga vrati previše rezultata da bi bila upotrebljiva. U tom je slučaju lijepo izložiti mehanizam filtriranja koji može ponoviti isto pretraživanje, samo uz sužavanje rezultata.

Evo primjera gdje sužavamo članke koje je autor napisao, samo na one s određenom oznakom:

@Query ("{\" bool \ ": {\" must \ ":" + "{\" match \ ": {\" author.name \ ": \"? 0 \ "}}," + "\ "filter \": {\ "pojam \": {\ "oznake \": \ "? 1 \"}}}} ")) Stranica findByAuthorsNameAndFilteredTagQuery (Ime niza, Oznaka niza, stranica koja se može stranicati);

Opet, Spring Data radi sav posao umjesto nas.

Pogledajmo i kako sami konstruirati ovaj upit:

QueryBuilder builder = boolQuery (). Must (ugniježđeniQuery ("autori", boolQuery (). Mora (termQuery ("ime autora", "doe"), ScoreMode.None)) .filter (termQuery ("oznake", " elastično pretraživanje "));

Ovu istu tehniku ​​možemo, naravno, koristiti za filtriranje bilo kojeg drugog polja u dokumentu. Ali oznake su posebno korisne za ovaj slučaj upotrebe.

Evo kako koristiti gornji upit:

SearchQuery searchQuery = novi NativeSearchQueryBuilder (). WithQuery (graditelj) .build (); Lista članaka = elasticsearchTemplate.queryForList (searchQuery, Article.class); // članci sadrže [1, 4] assertThat (articleByTags, containsInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (4))));

4. Kontekst filtra

Kada gradimo upit, moramo razlikovati kontekst upita i kontekst filtra. Svaki upit u Elasticsearch-u ima kontekst upita, pa bismo ih trebali naviknuti vidjeti.

Ne podržava svaka vrsta upita kontekst filtra. Stoga, ako želimo filtrirati oznake, moramo znati koje vrste upita možemo koristiti.

The bool upit ima dva načina za pristup kontekstu filtra. Prvi parametar, filtar, je onaj koji koristimo gore. Također možemo koristiti i ne smije parametar za aktiviranje konteksta.

Sljedeća vrsta upita koju možemo filtrirati je rezultat konstante. To je korisno kada uu želite zamijeniti kontekst upita rezultatima filtra i dodijeliti svakom rezultatu isti rezultat.

Posljednja vrsta upita koju možemo filtrirati na temelju oznaka je agregacija filtra. To nam omogućuje stvaranje grupa za agregiranje na temelju rezultata našeg filtra. Drugim riječima, sve članke možemo grupirati prema oznakama u našem rezultatu agregiranja.

5. Napredno označavanje

Do sada smo razgovarali samo o označavanju pomoću najosnovnije implementacije. Sljedeći logični korak je stvaranje tagova koji su sami parovi ključ / vrijednost. To bi nam omogućilo da postanemo još ljubitelji naših upita i filtara.

Na primjer, svoje polje oznake mogli bismo promijeniti u ovo:

Oznake privatnog popisa @Field (vrsta = ugniježđeno);

Tada bismo samo promijenili filtre kako bi se koristili nestedQuery vrste.

Jednom kad shvatimo kako koristiti parovi ključ / vrijednost mali je korak do upotrebe složenih objekata kao naše oznake. Neće puno implementacija trebati cjeloviti objekt kao oznaku, ali dobro je znati da imamo ovu opciju ako je trebamo.

6. Zaključak

U ovom smo članku pokrili osnove implementacije označavanja pomoću Elasticsearch-a.

Kao i uvijek, primjeri se mogu naći na GitHubu.

Sljedeći » Jednostavna provedba označavanja s dnom postojanosti JPA

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ