Introduksjon til dvalesøk

1. Oversikt

I denne artikkelen vil vi diskutere det grunnleggende om dvalemodus, hvordan du konfigurerer det, og vi vil implementere noen enkle spørsmål.

2. Grunnleggende om dvalesøk

Når vi må implementere søkefunksjonalitet i fulltekst, er det alltid et pluss å bruke verktøy vi allerede er kjent med.

Hvis vi allerede bruker dvalemodus og JPA for ORM, er vi bare ett skritt fra dvalemodus.

Hibernate Search integrerer Apache Lucene, et høytytende og utvidbart søkemotorbibliotek med fulltekst skrevet på Java. Dette kombinerer kraften til Lucene med enkelheten i dvalemodus og JPA.

Enkelt sagt, vi må bare legge til noen ekstra merknader i domeneklassene våre, og verktøyet tar seg av ting som database / indeks synkronisering.

Hibernate Search gir også en elastisk søkintegrasjon; Men siden det fremdeles er i et eksperimentelt stadium, vil vi fokusere på Lucene her.

3. Konfigurasjoner

3.1. Maven avhengigheter

Før vi begynner, må vi først legge til de nødvendige avhengighetene til våre pom.xml:

 org. dvale dvalemodus-søk-orm 5.8.2.Final 

For enkelhets skyld vil vi bruke H2 som vår database:

 com.h2database h2 1.4.196 

3.2. Konfigurasjoner

Vi må også spesifisere hvor Lucene skal lagre indeksen.

Dette kan gjøres via eiendommen hibernate.search.default.directory_provider.

Vi velger filsystem, som er det mest enkle alternativet for brukssaken vår. Flere alternativer er oppført i den offisielle dokumentasjonen. Filsystem-master/filsystem-slave og infinispan er bemerkelsesverdige for klyngede applikasjoner, der indeksen må synkroniseres mellom noder.

Vi må også definere en standard basekatalog der indekser skal lagres:

hibernate.search.default.directory_provider = filsystem hibernate.search.default.indexBase = / data / index / default

4. Modellklassene

Etter konfigurasjonen er vi nå klare til å spesifisere modellen vår.

På toppen av JPA-merknadene @Enhet og @Bord, må vi legge til en @Indexed kommentar. Det forteller Hibernate Search at enheten Produkt skal indekseres.

Etter det må vi definere de nødvendige attributtene som søkbare ved å legge til en @Felt kommentar:

@Entity @Indexed @Table (name = "product") offentlig klasse Produkt {@Id privat int id; @Field (termVector = TermVector.YES) privat streng produktnavn; @Field (termVector = TermVector.YES) privat strengbeskrivelse; @Field privat int-minne; // getters, setters, and constructors}

De termVector = TermVector.YES attributtet vil være nødvendig for «Mer som dette» -spørringen senere.

5. Å bygge Lucene-indeksen

Før du starter de faktiske spørsmålene, vi må utløse Lucene til å bygge indeksen i utgangspunktet:

FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager (entityManager); fullTextEntityManager.createIndexer (). startAndWait ();

Etter denne første byggingen vil Hibernate Search sørge for å holde indeksen oppdatert. Dvs. vi kan opprette, manipulere og slette enheter via EntityManager som vanlig.

Merk: Vi må sørge for at enheter er forpliktet til databasen før de kan oppdages og indekseres av Lucene (forresten, dette er også grunnen til at den første testdataimporten i eksemplene våre med kodetest kommer i en dedikert JUnit-testsak, kommentert med @Begå).

6. Bygging og utføring av spørsmål

Nå er vi klare for å lage vårt første spørsmål.

I det følgende avsnittet, vi viser den generelle arbeidsflyten for å forberede og utføre et spørsmål.

Deretter oppretter vi noen eksempler på spørsmål for de viktigste spørringstypene.

6.1. Generell arbeidsflyt for å opprette og utføre en spørring

Forberedelse og utføring av et spørsmål generelt består av fire trinn:

I trinn 1 må vi skaffe en JPA FullTextEntityManager og fra det a QueryBuilder:

FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager (entityManager); QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory () .buildQueryBuilder (). ForEntity (Product.class) .get ();

I trinn 2 oppretter vi et Lucene-spørsmål via dvalemodus DSL:

org.apache.lucene.search.Query query = queryBuilder .keyword () .onField ("productName") .matching ("iphone") .createQuery ();

I trinn 3 vil vi pakke Lucene-spørringen inn i en dvalemodus-spørring:

org.hibernate.search.jpa.FullTextQuery jpaQuery = fullTextEntityManager.createFullTextQuery (spørring, Product.class);

Til slutt, i trinn 4, utfører vi spørringen:

Listeresultater = jpaQuery.getResultList ();

Merk: Lucene sorterer som standard resultatene etter relevans.

Trinn 1, 3 og 4 er de samme for alle søketyper.

I det følgende vil vi fokusere på trinn 2, jeg. e. hvordan du lager forskjellige typer spørsmål.

6.2. Søkeordsspørsmål

Den mest grunnleggende brukssaken er søker etter et bestemt ord.

Dette gjorde vi egentlig allerede i forrige avsnitt:

Query keywordQuery = queryBuilder .keyword () .onField ("productName") .matching ("iphone") .createQuery ();

Her, nøkkelord () spesifiserer at vi leter etter ett bestemt ord, onField () forteller Lucene hvor hun skal lete og matchende() hva du skal se etter.

6.3. Fuzzy Queries

Fuzzy-spørsmål fungerer som søkeord, bortsett fra det vi kan definere en grense for "uklarhet", over hvilken Lucene skal godta de to begrepene som samsvarende.

Av withEditDistanceUpTo (), vi kan definere hvor mye et begrep kan avvike fra det andre. Den kan settes til 0, 1 og 2, hvor standardverdien er 2 (Merk: denne begrensningen kommer fra Lucenens implementering).

Av withPrefixLength (), kan vi definere lengden på prefikset som skal ignoreres av uklarheten:

Query fuzzyQuery = queryBuilder .keyword () .fuzzy () .withEditDistanceUpTo (2) .withPrefixLength (0) .onField ("productName") .matching ("iPhaen") .createQuery ();

6.4. Jokertegnspørsmål

Dvalesøk gjør det også mulig for oss å utføre jokertegnspørsmål, dvs. e. spørsmål som en del av et ord er ukjent for.

For dette kan vi bruke “?” for en enkelt karakter, og “*” for hvilken som helst tegnsekvens:

Query wildcardQuery = queryBuilder .keyword () .wildcard () .onField ("productName") .matching ("Z *") .createQuery ();

6.5. Setningsspørsmål

Hvis vi vil søke etter mer enn ett ord, kan vi bruke frasespørsmål. Vi kan enten se for eksakte eller for omtrentlige setninger, ved hjelp av uttrykk() og withSlop (), hvis nødvendig. Slopfaktoren definerer antall andre ord som er tillatt i setningen:

Query phraseQuery = queryBuilder .phrase () .withSlop (1) .onField ("description") .ence ("with wireless charge") .createQuery ();

6.6. Enkle spørringsstrengsspørsmål

Med de forrige spørringstypene måtte vi spesifisere spørringstypen eksplisitt.

Hvis vi vil gi brukerne mer kraft, kan vi bruke enkle spørringsstrengspørsmål: ved det kan han definere sine egne spørsmål ved kjøretid.

Følgende spørringstyper støttes:

  • boolsk (OG bruker "+", ELLER bruker "|", IKKE bruker "-")
  • prefiks (prefiks *)
  • setning (“noe uttrykk”)
  • forrang (ved hjelp av parenteser)
  • uklar (uklar ~ 2)
  • nær operatør for frase spørsmål (“noen fraser” ~ 3)

Følgende eksempel vil kombinere fuzzy, frase og boolske spørsmål:

Query simpleQueryStringQuery = queryBuilder .simpleQueryString () .onFields ("productName", "description") .matching ("Aple ~ 2 + \" iPhone X \ "+ (256 | 128)") .createQuery ();

6.7. Område spørsmål

Områdespørsmål søker etter enverdi mellom gitte grenser. Dette kan brukes på tall, datoer, tidsstempler og strenger:

Query rangeQuery = queryBuilder .range () .onField ("memory") .from (64) .to (256) .createQuery ();

6.8. Flere som disse spørsmålene

Den siste spørringstypen vår er “Mer som dette”- spørring. For dette tilbyr vi en enhet, og Dvalesøk returnerer en liste med lignende enheter, hver med likhetspoeng.

Som nevnt før, termVector = TermVector.YES attributt i vår modellklasse er nødvendig for denne saken: den forteller Lucene å lagre frekvensen for hver periode under indeksering.

Basert på dette vil likheten bli beregnet ved utførelsestid for spørring:

Query moreLikeThisQuery = queryBuilder .moreLikeThis () .comparingField ("productName"). BoostedTo (10f) .andField ("description"). BoostedTo (1f) .toEntity (entity) .createQuery (); Listeresultater = (Liste) fullTextEntityManager .createFullTextQuery (moreLikeThisQuery, Product.class) .setProjection (ProjectionConstants.THIS, ProjectionConstants.SCORE) .getResultList ();

6.9. Søker mer enn ett felt

Inntil nå opprettet vi bare spørsmål for å søke etter ett attributt ved hjelp av onField ().

Avhengig av brukssaken, vi kan også søke i to eller flere attributter:

Query luceneQuery = queryBuilder .keyword () .onFields ("productName", "description") .matching (text) .createQuery ();

Videre Vi kan spesifisere hvert attributt som skal søkes separat, e. g. hvis vi vil definere et løft for ett attributt:

Query moreLikeThisQuery = queryBuilder .moreLikeThis () .comparingField ("productName"). BoostedTo (10f) .andField ("description"). BoostedTo (1f) .toEntity (entity) .createQuery ();

6.10. Kombinere spørsmål

Til slutt støtter Hibernate Search også å kombinere spørsmål ved hjelp av forskjellige strategier:

  • BØR: spørringen skal inneholde de samsvarende elementene i undersøket
  • MÅ: spørringen må inneholde de samsvarende elementene i undersøket
  • MÅ IKKE: spørringen må ikke inneholde de samsvarende elementene i undersøket

Aggregasjonene er ligner på de boolske AND, OR og IKKE. Navnene er imidlertid forskjellige for å understreke at de også har innvirkning på relevansen.

For eksempel, a BØR mellom to spørsmål ligner på boolsk ELLER: hvis en av de to spørsmålene har samsvar, vil denne kampen returneres.

Imidlertid, hvis begge spørsmålene samsvarer, vil kampen ha høyere relevans sammenlignet med hvis bare en spørring samsvarer med:

Query combinedQuery = queryBuilder .bool () .must (queryBuilder.keyword () .onField ("productName"). Matching ("apple") .createQuery ()) .must (queryBuilder.range () .onField ("memory") .fra (64) .to (256) .createQuery ()) .should (queryBuilder.phrase () .onField ("description"). setning ("face id") .createQuery ()) .must (queryBuilder.keyword ( ) .onField ("productName"). matching ("samsung") .createQuery ()) .not () .createQuery ();

7. Konklusjon

I denne artikkelen diskuterte vi det grunnleggende i Hibernate Search og viste hvordan du implementerer de viktigste spørringstypene. Mer avanserte emner finner du i den offisielle dokumentasjonen.

Som alltid er hele kildekoden til eksemplene tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found