Introduksjon til Lucene

Introduksjon til Lucene
I denne leksjonen vil vi forstå arbeidet bak en av de kraftigste søkemotorene for fulltekst, Apache Lucene. Med Apache Lucene kan vi bruke APIene den utsetter på mange programmeringsspråk og bygger funksjonene vi trenger. Lucene er en av de kraftigste motorene som Elasticsearch er bygget opp på. Før vi begynner med en applikasjon som demonstrerer Apache Lucene, vil vi forstå hvordan Lucene fungerer og mange av komponentene. La oss komme i gang.

Hvorfor er Lucene nødvendig?

Søk er en av de vanligste operasjonene vi utfører flere ganger om dagen. Dette søket kan være på flere websider som finnes på nettet eller en musikkapplikasjon eller et kodelager eller en kombinasjon av alle disse. Man kan tro at en enkel relasjonsdatabase også kan støtte søk. Dette er riktig. Databaser som MySQL støtter fulltekstsøk. Men hva med nettet eller en musikkapplikasjon eller et kodelagring eller en kombinasjon av alle disse? Databasen kan ikke lagre disse dataene i kolonnene sine. Selv om det gjorde det, vil det ta en uakseptabel tid å kjøre søket så stort.

En søkemotor i fulltekst er i stand til å kjøre et søk på millioner av filer samtidig. Hastigheten som data lagres i en applikasjon i dag er enorm. Å kjøre fulltekstsøk på denne typen volum av data er en vanskelig oppgave. Dette er fordi informasjonen vi trenger kan eksistere i en enkelt fil av milliarder filer som holdes på nettet.

Hvordan Lucene fungerer?

Det åpenbare spørsmålet som skal komme til tankene dine er, hvordan er Lucene så raskt i å løpe spørsmål i fulltekst? Svaret på dette er selvfølgelig ved hjelp av indekser det skaper. Men i stedet for å lage en klassisk indeks, bruker Lucene Inverterte indekser.

I en klassisk indeks, for hvert dokument, samler vi inn den fullstendige listen over ord eller begrep dokumentet inneholder. I en omvendt indeks, for hvert ord i alle dokumentene, lagrer vi hvilket dokument og plassering av dette ordet/begrepet kan bli funnet på. Dette er en høy standard algoritme som gjør søket veldig enkelt. Tenk på følgende eksempel på å lage en klassisk indeks:

Doc1 -> "this", "is", "Simple", "Lucene", "Sample", "Classic", "inverted", "index"
Doc2 -> "Running", "Elasticsearch", "Ubuntu", "Update"
Doc3 -> "Rabbitmq", "Lucene", "Kafka", "", "Spring", "Boot"

Hvis vi bruker omvendt indeks, vil vi ha indekser som:

Dette -> (2, 71)
Lucene -> (1, 9), (12,87)
Apache -> (12, 91)
Framework -> (32, 11)

Inverterte indekser er mye enklere å vedlikeholde. Anta at hvis vi ønsker å finne apache i mine vilkår, vil jeg ha svar med omvendte indekser, mens med klassisk søk ​​vil kjøres på komplette dokumenter som kanskje ikke har vært mulig å kjøre i sanntidsscenarier.

Lucene arbeidsflyt

Før Lucene faktisk kan søke i dataene, må de utføre trinn. La oss visualisere disse trinnene for en bedre forståelse:

Lucene arbeidsflyt

Som vist i diagrammet, er det dette som skjer i Lucene:

  1. Lucene blir matet dokumentene og andre datakilder
  2. For hvert dokument konverterer Lucene først disse dataene til ren tekst, og deretter konverterer analysatorene denne kilden til ren tekst
  3. For hvert begrep i vanlig tekst opprettes de omvendte indeksene
  4. Indeksene er klare til å bli søkt

Med denne arbeidsflyten er Lucene en veldig sterk søkemotor for fulltekst. Men dette er den eneste delen Lucene oppfyller. Vi må utføre arbeidet selv. La oss se på komponentene i indeksering som trengs.

Lucene -komponenter

I dette avsnittet vil vi beskrive de grunnleggende komponentene og de grunnleggende Lucene -klassene som brukes til å lage indekser:

  • Kataloger: En Lucene -indeks lagrer data i normale filsystemdirektoer eller i minnet hvis du trenger mer ytelse. Det er helt appene valg å lagre data uansett hvor den vil, en database, RAM eller disken.
  • Dokumenter: Dataene vi lever til Lucene-motoren må konverteres til ren tekst. For å gjøre dette, lager vi et dokumentobjekt som representerer den datakilden. Senere, når vi kjører et søk, vil vi som et resultat få en liste over dokumentobjekter som tilfredsstiller spørringen vi gikk.
  • Enger: Dokumenter er befolket med en samling felt. Et felt er ganske enkelt et par av (navn, verdi) gjenstander. Så mens vi oppretter et nytt dokumentobjekt, må vi fylle det med den typen sammenkoblede data. Når et felt er omvendt indeksert, er verdien av feltet tokenisert og er tilgjengelig for søk. Nå, mens vi bruker felt, er det ikke viktig å lagre det faktiske paret, men bare den omvendte indekserte. På denne måten kan vi bestemme hvilke data som bare er søkbare og ikke viktige for å bli lagret. La oss se på et eksempel her:

    Feltindeksering

    I tabellen over bestemte vi oss for å lagre noen felt og andre ikke lagret. Kroppsfeltet er ikke lagret, men indeksert. Dette betyr at e -posten vil bli returnert som et resultat når spørringen om et av vilkårene for kroppsinnholdet kjøres.

  • Vilkår: Vilkår representerer et ord fra teksten. Begrepene blir trukket ut fra analysen og tokenisering av felts verdier, således Begrepet er den minste enheten som søket kjøres.
  • Analysatorer: En analysator er den mest avgjørende delen av indekserings- og søkeprosessen. Det er analysatoren som conevrts vanlig tekst i symboler og vilkår slik at de kan søkes. Vel, det er ikke det eneste ansvaret for en analysator. En analysator bruker en tokenizer for å lage symboler. En analysator gjør også følgende oppgaver:
    • Stemming: En analysator konverterer ordet til en stilk. Dette betyr at 'blomster' blir konvertert til stamordet 'blomst'. Så når et søk etter 'blomst' kjøres, blir dokumentet returnert.
    • Filtrering: En analysator filtrerer også stoppordene som '', 'er' osv. Ettersom disse ordene ikke tiltrekker seg noen spørsmål som skal kjøres og ikke er produktive.
    • Normalisering: Denne prosessen fjerner aksenter og andre karaktermerker.

    Dette er bare det normale ansvaret til Standardanalyzer.

Eksempelprogram

Vi vil bruke en av de mange Maven -arketypene for å lage et eksempelprosjekt for vårt eksempel. For å opprette prosjektet utfør følgende kommando i en katalog som du vil bruke som arbeidsområde:

MVN arketype: generere -dgroupid = com.Linuxhint.Eksempel -DARTIFACTID = LH -LuceneExample -DarChetypeArtIfactID = Maven -Archetype -QuickStart -DinterActivemode = FALSE

Hvis du kjører Maven for første gang, vil det ta noen sekunder å oppnå genereringskommandoen fordi Maven må laste ned alle nødvendige plugins og gjenstander for å gjøre generasjonsoppgaven. Slik ser prosjektutgangen ut:

Prosjektoppsett

Når du har opprettet prosjektet, kan du gjerne åpne det i din favoritt IDE. Neste trinn er å legge til passende Maven -avhengigheter til prosjektet. Her er POM.XML -fil med passende avhengigheter:



org.Apache.Lucene
Lucene-core
4.6.0


org.Apache.Lucene
Lucene-analysere-vanlige
4.6.0

Til slutt, for å forstå alle glassene som blir lagt til prosjektet når vi la til denne avhengigheten, kan vi kjøre en enkel Maven -kommando som lar oss se et komplett avhengighetstre for et prosjekt når vi legger til noen avhengigheter til det. Her er en kommando som vi kan bruke:

MVN -avhengighet: tre

Når vi kjører denne kommandoen, vil den vise oss følgende avhengighetstre:

Til slutt lager vi en SimpleIndexer -klasse som kjører

pakke com.Linuxhint.eksempel;
Importer Java.io.Fil;
Importer Java.io.Filerader;
Importer Java.io.IOException;
Import org.Apache.Lucene.analyse.Analysator;
Import org.Apache.Lucene.analyse.standard.Standardanalyzer;
Import org.Apache.Lucene.dokument.Dokument;
Import org.Apache.Lucene.dokument.Storedfield;
Import org.Apache.Lucene.dokument.Tekstfelt;
Import org.Apache.Lucene.indeks.Indexwriter;
Import org.Apache.Lucene.indeks.IndexWriterConfig;
Import org.Apache.Lucene.butikk.Fsdirectory;
Import org.Apache.Lucene.util.Versjon;
offentlig klasse SimpleIndexer
privat statisk final String indexDirectory = "/brukere/shubham/et sted/lh-luceneexample/indeks";
privat statisk finalstreng DirTobeIndexed = "/brukere/shubham/et sted/lh-luceneexample/src/main/java/com/linuxhint/eksempel";
public static void main (String [] args) kaster unntak
File IndexDir = ny fil (IndexDirectory);
Fildatadir = ny fil (DirTobeIndexed);
SimpleIndexer indexer = new SimpleIndexer ();
int numIndexed = indekser.indeks (indeksdir, datadir);
System.ute.println ("Total filer indeksert" + numIndexed);

Privat int -indeks (File IndexDir, File Datadir) kaster IOException
Analyzer Analyzer = New StandardAnalyzer (versjon.Lucene_46);
IndexWriterConfig Config = New IndexWriterConfig (versjon.Lucene_46,
analysator);
IndexWriter IndexWriter = New IndexWriter (FSDirectory.Åpen (IndexDir),
konfigurasjon);
Fil [] filer = datadir.ListFiles ();
for (fil f: filer)
System.ute.println ("Indekseringsfil" + f.getCanonicalPath ());
Dokument doc = nytt dokument ();
Doc.Legg til (ny TextField ("Innhold", ny FileReader (F)));
Doc.Legg til (New Storedfield ("Filname", f.getCanonicalPath ()));
Indexwriter.addDocument (doc);

int numIndexed = indexwriter.MaxDoc ();
Indexwriter.Lukk();
Returnumindexed;

I denne koden laget vi nettopp et dokumentforekomst og la til et nytt felt som representerer filinnholdet. Her er utdataene vi får når vi kjører denne filen:

Indekseringsfil/brukere/shubham/et sted/lh-lucenexample/src/main/java/com/Linuxhint/Eksempel/SimpleIndexer.Java
Totale filer indeksert 1

Det opprettes også en ny katalog i prosjektet med følgende innhold:

Indeksdata

Vi vil analysere hva alle filer opprettes i disse indeksene i flere leksjoner for å komme på Lucene.

Konklusjon

I denne leksjonen så vi på hvordan Apache Lucene fungerer, og vi laget også et enkelt eksempelprogram som var basert på Maven og Java.