Jednoduchá implementácia značkovania pomocou Elasticsearch

Perzistencia hore

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ Tento článok je súčasťou série: • Implementácia jednoduchého označovania pomocou Elasticsearch (aktuálny článok) • Implementácia jednoduchého označovania pomocou JPA

• Pokročilá implementácia označovania pomocou JPA

• Jednoduchá implementácia označovania pomocou MongoDB

1. Prehľad

Označovanie je bežný návrhový vzor, ​​ktorý nám umožňuje kategorizovať a filtrovať položky v našom dátovom modeli.

V tomto článku implementujeme značkovanie pomocou Spring a Elasticsearch. Budeme používať Spring Data aj Elasticsearch API.

Najskôr nejdeme o základy získavania Elasticsearch a Spring Data - môžete ich preskúmať tu.

2. Pridávanie značiek

Najjednoduchšou implementáciou označovania je pole reťazcov. Môžeme to implementovať pridaním nového poľa do nášho dátového modelu, ako je toto:

@Document (indexName = "blog", type = "článok") verejná trieda článok {// ... @Field (type = kľúčové slovo) súkromné ​​reťazce [] značky; // ...}

Všimnite si použitie Kľúčové slovo typ poľa. Chceme iba presnú zhodu našich značiek na filtrovanie výsledku. To nám umožňuje používať podobné, ale samostatné značky ako elasticsearchIsAwesome a elasticsearchIsTerrible.

Analyzované polia by vrátili čiastočné prístupy, čo je v tomto prípade nesprávne správanie.

3. Stavebné dotazy

Značky nám umožňujú zaujímavo manipulovať s našimi dotazmi. Môžeme ich prehľadať ako každé iné pole, alebo pomocou nich môžeme filtrovať výsledky match_all dotazy. Môžeme ich tiež použiť pri iných dotazoch na zúženie našich výsledkov.

3.1. Hľadanie značiek

Nové značka pole, ktoré sme vytvorili na našom modeli, je ako každé iné pole v našom indexe. Môžeme vyhľadať každú entitu, ktorá má konkrétnu značku, ako je táto:

@Query ("{\" bool \ ": {\" must \ ": [{\" match \ ": {\" tags \ ": \"? 0 \ "}}]}}}") Stránka findByTagUsingDeclaredQuery (reťazec značka, stránkovateľné stránkovateľné);

Tento príklad používa na zostavenie nášho dotazu Spring Data Repository, ale rovnako rýchlo môžeme použiť šablónu Rest na manuálne zadanie dotazu na klaster Elasticsearch.

Podobne môžeme použiť Elasticsearch API:

boolQuery (). must (termQuery ("tagy", "elasticsearch"));

Predpokladajme, že v našom indexe používame nasledujúce dokumenty:

[{"id": 1, "title": "Spring Data Elasticsearch", "autori": [{"name": "John Doe"}, {"name": "John Smith"}], "tags": ["elasticsearch", "jarné údaje"]}, {"id": 2, "title": "Vyhľadávače", "autori": [{"name": "John Doe"}], "tagy": [ "search engine", "tutorial"]}, {"id": 3, "title": "Druhý článok o službe Elasticsearch", "autori": [{"name": "John Smith"}], "tags": ["elasticsearch", "jarné údaje"]}, {"id": 4, "title": "Elasticsearch Tutorial", "autori": [{"name": "John Doe"}], "tagy": [ "elasticsearch"]},]

Teraz môžeme použiť tento dotaz:

Stránka articleByTags = articleService.findByTagUsingDeclaredQuery ("elasticsearch", PageRequest.of (0, 10)); // articleByTags bude obsahovať 3 články [1, 3, 4] assertThat (articleByTags, containsInAnyOrder (hasProperty ("id", je (1)), hasProperty ("id", je (3)), hasProperty ("id", je (4))));

3.2. Filtrovanie všetkých dokumentov

Spoločným návrhovým vzorom je vytvorenie a Filtrované zobrazenie zoznamu v používateľskom rozhraní, ktoré zobrazuje všetky entity, ale tiež umožňuje používateľovi filtrovať na základe rôznych kritérií.

Povedzme, že chceme vrátiť všetky články filtrované podľa akejkoľvek značky, ktorú si používateľ vyberie:

@Query ("{\" bool \ ": {\" must \ ":" + "{\" match_all \ ": {}}, \" filter \ ": {\" term \ ": {\" tagy \ ": \"? 0 \ "}}}}") Stránka findByFilteredTagQuery (reťazcová značka, stránkovateľné stránkovateľné);

Opäť používame Spring Data na zostavenie nášho deklarovaného dotazu.

Následne sa dotaz, ktorý používame, rozdelí na dve časti. Bodovací dotaz je prvý výraz, v tomto prípade match_all. Nasleduje dotaz na filter a informuje Elasticsearch, ktoré výsledky má zahodiť.

Tento dotaz používame takto:

Stránka articleByTags = articleService.findByFilteredTagQuery ("elasticsearch", PageRequest.of (0, 10)); // articleByTags bude obsahovať 3 články [1, 3, 4] assertThat (articleByTags, containsInAnyOrder (hasProperty ("id", je (1)), hasProperty ("id", je (3)), hasProperty ("id", je (4))));

Je dôležité si uvedomiť, že aj keď to vráti rovnaké výsledky ako v našom príklade vyššie, tento dopyt bude fungovať lepšie.

3.3. Filtrovanie dotazov

Vyhľadávanie niekedy vráti príliš veľa výsledkov, aby bolo použiteľné. V takom prípade je pekné vystaviť filtračný mechanizmus, ktorý dokáže znova spustiť rovnaké vyhľadávanie, len s obmedzenými výsledkami.

Tu je príklad, keď zúžime články, ktoré autor napísal, iba na tie, ktoré majú konkrétnu značku:

@Query ("{\" bool \ ": {\" must \ ":" + "{\" zápas \ ": {\" autori.name \ ": \"? 0 \ "}}," + "\ "filter \": {\ "termín \": {\ "tagy \": \ "? 1 \"}}}} ") Stránka findByAuthorsNameAndFilteredTagQuery (názov reťazca, značka reťazca, stránkovateľné stránkovateľné);

Spring Data opäť robí všetku prácu za nás.

Pozrime sa tiež na to, ako môžeme tento dopyt skonštruovať sami:

Builder QueryBuilder = boolQuery (). Must (nestedQuery ("autori", boolQuery (). Must (termQuery ("autori.name", "doe")), ScoreMode.None)) .filter (termQuery ("tagy", " elasticsearch "));

Rovnakou technikou môžeme samozrejme filtrovať ktorékoľvek ďalšie pole v dokumente. Značky sa ale na tento prípad použitia zvlášť dobre hodí.

Vyššie uvedený dotaz môžete použiť takto:

SearchQuery searchQuery = nový NativeSearchQueryBuilder (). WithQuery (builder) .build (); Zoznam článkov = elasticsearchTemplate.queryForList (searchQuery, Article.class); // články obsahujú [1, 4] assertThat (articleByTags, containsInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (4))));

4. Kontext filtra

Keď zostavujeme dotaz, musíme rozlišovať medzi kontextom dotazu a kontextom filtra. Každý dopyt v Elasticsearch má kontext dotazu, takže by sme mali byť zvyknutí ich vidieť.

Nie každý typ dotazu podporuje kontext filtra. Preto, ak chceme filtrovať podľa značiek, musíme vedieť, ktoré typy dotazov môžeme použiť.

The bool dotaz má dva spôsoby prístupu k kontextu filtra. Prvý parameter, filter, je ten, ktorý používame vyššie. Môžeme tiež použiť a nesmieš parameter na aktiváciu kontextu.

Ďalší typ dotazu, ktorý môžeme filtrovať, je konštantné_skóre. Je to užitočné, keď chcete nahradiť kontext dotazu výsledkami filtra a každému výsledku priradiť rovnaké skóre.

Konečný typ dotazu, ktorý môžeme filtrovať na základe značiek, je agregácia filtra. To nám umožňuje vytvárať agregačné skupiny na základe výsledkov nášho filtra. Inými slovami, všetky naše články môžeme zoskupiť podľa značiek.

5. Pokročilé označovanie

Doteraz sme hovorili iba o označovaní pomocou najzákladnejšej implementácie. Ďalším logickým krokom je vytvorenie značiek, ktoré sú samy o sebe páry kľúč - hodnota. To by nám umožnilo získať si s našimi dopytmi a filtrami ešte väčšiu obľubu.

Mohli by sme napríklad zmeniť naše pole značky na toto:

@Field (type = Nested) súkromné ​​značky zoznamu;

Potom by sme len zmenili naše filtre na použitie nestedQuery typy.

Keď pochopíme, ako sa používa páry kľúč - hodnota je to malý krok k použitiu zložitých objektov ako našej značky. Nie veľa implementácií bude potrebovať celý objekt ako značku, ale je dobré vedieť, že túto možnosť máme, ak ju budeme vyžadovať.

6. Záver

V tomto článku sme sa venovali základom implementácie značkovania pomocou Elasticsearch.

Ako vždy, príklady nájdete na GitHub.

Ďalšie » Jednoduchá implementácia značkovania so spodnou časťou Perzistencia JPA

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ