Zakaj je potreben Lucene??
Iskanje je ena najpogostejših operacij, ki jih izvajamo večkrat na dan. To iskanje je lahko na več spletnih straneh, ki obstajajo v spletu ali v glasbeni aplikaciji ali v skladišču kod ali v kombinaciji vseh teh. Lahko bi pomislili, da lahko tudi preprosta relacijska baza podatkov podpira iskanje. To je pravilno. Podatkovne baze, kot je MySQL, podpirajo iskanje po celotnem besedilu. Kaj pa splet ali glasbena aplikacija ali shramba kod ali kombinacija vseh teh? Baza podatkov ne more shraniti teh podatkov v stolpce. Tudi če bi se zgodilo, bo trajalo nesprejemljivo veliko časa, da se iskanje začne tako veliko.
Polnobesedilni iskalnik je sposoben zagnati iskalno poizvedbo na milijone datotek hkrati. Hitrost shranjevanja podatkov v aplikaciji je danes ogromna. Zagon polnobesedilnega iskanja pri tovrstnem obsegu podatkov je težka naloga. To je zato, ker bi informacije, ki jih potrebujemo, morda obstajale v eni sami datoteki od milijard datotek, shranjenih v spletu.
Kako deluje Lucene?
Očitno vprašanje, ki bi vam moralo pasti na pamet, je, kako Lucene tako hitro izvaja poizvedbe po celotnem besedilu? Odgovor na to je seveda s pomočjo indeksov, ki jih ustvarja. Toda namesto da bi ustvaril klasični indeks, Lucene uporablja Obrnjeni indeksi.
V klasičnem indeksu za vsak dokument zberemo celoten seznam besed ali izrazov, ki jih dokument vsebuje. V obrnjenem indeksu za vsako besedo v vseh dokumentih shranimo, kateri dokument in položaj te besede / izraza lahko najdemo na. To je visokokakovosten algoritem, ki zelo olajša iskanje. Upoštevajte naslednji primer ustvarjanja klasičnega indeksa:
Doc1 -> "To", "je", "preprosto", "Lucen", "vzorec", "klasična", "obrnjena", "indeks"Doc2 -> "Izvajanje", "Elasticsearch", "Ubuntu", "Posodobitev"
Doc3 -> "RabbitMQ", "Lucene", "Kafka", "", "Spring", "Boot"
Če uporabimo obrnjen indeks, bomo imeli indekse, kot so:
To -> (2, 71)Lucen -> (1, 9), (12,87)
Apači -> (12, 91)
Okvir -> (32, 11)
Obrnjene indekse je veliko lažje vzdrževati. Recimo, da če želimo po mojih besedah najti Apache, bom takoj dobil odgovore z obrnjenimi indeksi, medtem ko bo pri klasičnem iskanju potekalo po celotnih dokumentih, ki jih v realnem času morda ne bi bilo mogoče zagnati.
Potek dela lucena
Preden lahko Lucene dejansko išče podatke, mora izvesti korake. Predstavljajmo si te korake za boljše razumevanje:
Potek dela lucena
Kot je prikazano na diagramu, se to zgodi v luceni:
- Lucene hranijo dokumenti in drugi viri podatkov
- Za vsak dokument Lucene te podatke najprej pretvori v navadno besedilo, nato pa jih analizatorji pretvorijo v navadno besedilo
- Za vsak izraz v golem besedilu se ustvarijo obrnjeni indeksi
- Indeksi so pripravljeni za iskanje
S tem potekom dela je Lucene zelo močan iskalnik celotnega besedila. Toda to je edini del, ki ga Lucene izpolni. Delo moramo opraviti sami. Poglejmo si potrebne komponente indeksiranja.
Lucenske komponente
V tem poglavju bomo opisali osnovne komponente in osnovne razrede lucena, ki se uporabljajo za ustvarjanje indeksov:
- Imeniki: Lucenski indeks shranjuje podatke v običajnih direktorijih datotečnega sistema ali v pomnilnik, če potrebujete večjo zmogljivost. Izbira aplikacij je, da shranijo podatke, kamor koli želijo, zbirko podatkov, RAM ali disk.
- Dokumenti: Podatke, ki jih dovajamo v lucenski motor, moramo pretvoriti v navadno besedilo. Za to naredimo objekt Document, ki predstavlja ta vir podatkov. Kasneje, ko zaženemo iskalno poizvedbo, bomo kot rezultat dobili seznam objektov Document, ki ustrezajo poizvedbi, ki smo jo poslali.
- Polja: Dokumenti so poseljeni z zbirko polj. Polje je preprosto par (ime, vrednost) predmetov. Torej, med ustvarjanjem novega predmeta Document ga moramo napolniti s tovrstnimi seznanjenimi podatki. Ko je polje inverzno indeksirano, se vrednost polja tokenizira in je na voljo za iskanje. Zdaj, medtem ko uporabljamo polja, ni pomembno, da shranimo dejanski par, ampak samo obrnjeno indeksirano. Tako se lahko odločimo, katere podatke je mogoče samo iskati in niso pomembni za shranjevanje. Oglejmo si primer tukaj:
Indeksiranje polja
V zgornji tabeli smo se odločili, da bomo shranili nekatera polja, druga pa ne. Polje telesa ni shranjeno, ampak indeksirano. To pomeni, da bo e-poštno sporočilo vrnjeno, ko se izvede poizvedba za enega od pogojev za vsebino telesa.
- Pogoji: Izrazi predstavljajo besedo iz besedila. Izrazi so torej povzeti iz analize in tokenizacije vrednosti polj Izraz je najmanjša enota, na kateri se izvaja iskanje.
- Analizatorji: Analizator je najpomembnejši del indeksiranja in iskanja. Analizator je tisti, ki navadno besedilo pretvori v žetone in pogoje, tako da jih je mogoče iskati. No, to ni edina odgovornost analizatorja. Analizator uporablja tokenizer za izdelavo žetonov. Analizator opravlja tudi naslednje naloge:
- Zarezovanje: Analizator pretvori besedo v steblo. To pomeni, da se "cvetovi" pretvorijo v matično besedo "cvet". Torej, ko se zažene iskanje "cvet", se dokument vrne.
- Filtriranje: Analizator filtrira tudi zaustavitvene besede, kot je 'The', 'is' itd. saj te besede ne pritegnejo nobenih poizvedb, ki jih je treba izvesti, in niso produktivne.
- Normalizacija: s tem postopkom se odstranijo poudarki in druge oznake znakov.
To je le običajna odgovornost StandardAnalyzerja.
Primer prijave
Za izdelavo vzorčnega projekta za naš primer bomo uporabili enega od mnogih arhetipov Maven. Če želite ustvariti projekt, v imeniku, ki ga boste uporabili kot delovni prostor, izvedite naslednji ukaz:
mvn arhetip: generiraj -DgroupId = com.linuxhint.primer -DartifactId = LH-LuceneExample -DarchetypeArtifactId = maven-archetype-quickstart -DinteractiveMode = falseČe prvič izvajate maven, bo trajalo nekaj sekund, da dokončate ukaz za generiranje, ker mora maven prenesti vse zahtevane vtičnike in artefakte, da bo opravil nalogo generiranja. Evo, kako izgleda rezultat projekta:
Nastavitev projekta
Ko ustvarite projekt, ga lahko odprete v svojem najljubšem IDE-ju. Naslednji korak je dodati projektu ustrezne odvisnosti Maven. Tu je pom.xml z ustreznimi odvisnostmi:
Na koncu, da bi razumeli vse JAR-je, ki so bili dodani projektu, ko smo dodali to odvisnost, lahko zaženemo preprost ukaz Maven, ki nam omogoča, da vidimo celotno drevo odvisnosti za projekt, ko mu dodamo nekaj odvisnosti. Tu je ukaz, ki ga lahko uporabimo:
odvisnost od mvn: drevoKo zaženemo ta ukaz, nam bo prikazal naslednje drevo odvisnosti:
Končno ustvarimo razred SimpleIndexer, ki se izvaja
uvoz java.io.Mapa;
uvoz java.io.FileReader;
uvoz java.io.IOException;
uvozna org.apache.lucen.analiza.Analizator;
uvozna org.apache.lucen.analiza.standard.StandardAnalyzer;
uvozna org.apache.lucen.dokument.Dokument;
uvozna org.apache.lucen.dokument.StoredField;
uvozna org.apache.lucen.dokument.TextField;
uvozna org.apache.lucen.indeks.IndexWriter;
uvozna org.apache.lucen.indeks.IndexWriterConfig;
uvozna org.apache.lucen.trgovina.FSDirectory;
uvozna org.apache.lucen.util.Različica;
javni razred SimpleIndexer
zasebni statični končni niz indexDirectory = "/ Uporabniki / shubham / nekje / LH-LuceneExample / Index";
zasebni statični končni niz dirToBeIndexed = "/ Uporabniki / shubham / nekje / LH-LuceneExample / src / main / java / com / linuxhint / example";
public static void main (String [] args) vrže izjemo
File indexDir = nova datoteka (indexDirectory);
Datoteka dataDir = nova datoteka (dirToBeIndexed);
Indeksator SimpleIndexer = nov SimpleIndexer ();
int numIndexed = indeksator.indeks (indexDir, dataDir);
Sistem.ven.println ("Skupaj indeksiranih datotek" + numIndexed);
zasebni indeks int (File indexDir, File dataDir) vrže IOException
Analizator analizator = nov StandardAnalyzer (različica.LUCENE_46);
IndexWriterConfig config = novo IndexWriterConfig (različica.LUCENE_46,
analizator);
IndexWriter indexWriter = nov IndexWriter (FSDirectory.odprto (indexDir),
config);
Datoteka [] files = dataDir.listFiles ();
za (Datoteka f: datoteke)
Sistem.ven.println ("Indeksiranje datoteke" + f.getCanonicalPath ());
Dokument doc = nov dokument ();
doc.add (new TextField ("content", new FileReader (f)));
doc.add (new StoredField ("fileName", f.getCanonicalPath ()));
indexWriter.addDocument (doc);
int numIndexed = indexWriter.maxDoc ();
indexWriter.blizu ();
vrnitev numIndexed;
V tej kodi smo pravkar izdelali primerek dokumenta in dodali novo polje, ki predstavlja vsebino datoteke. Tukaj je rezultat, ki ga dobimo, ko zaženemo to datoteko:
Indeksiranje datoteke / Uporabniki / shubham / nekje / LH-LuceneExample / src / main / java / com / linuxhint / example / SimpleIndexer.javaSkupaj indeksiranih datotek 1
Prav tako je znotraj projekta ustvarjen nov imenik z naslednjo vsebino:
Indeksni podatki
V več lekcijah o Luceni bomo analizirali, katere datoteke so ustvarjene v tem indeksu.
Zaključek
V tej lekciji smo si ogledali, kako deluje Apache Lucene, in naredili smo tudi preprost primer aplikacije, ki je temeljila na Mavenu in Javi.