Programmering

Lucene-søgemaskinen: Kraftig, fleksibel og gratis

Lad ikke det lave versionsnummer - 0,04 fra august 2000 - narre dig. Lucene-søgemaskinen er en robust, kraftfuld og fleksibel søgeværktøjssæt, der er klar til at tackle mange almindelige søgeproblemer. Og da den nu er tilgængelig under den mere fleksible LGPL open source-licens, er prisen (gratis!) Også rigtig.

Doug Cutting, en erfaren udvikler af tekstsøgnings- og hentningsværktøjer, oprettede Lucene. Cutting er den primære forfatter til V-Twin-søgemaskinen (en del af Apples Copland-operativsystemindsats) og er i øjeblikket seniorarkitekt hos Excite. Han designet Lucene til at gøre det let at tilføje indeksering og søgefunktioner til en bred vifte af applikationer, herunder:

  • Søgbar e-mail: En e-mail-applikation kan lade brugerne søge i arkiverede meddelelser og tilføje nye meddelelser til indekset, når de ankommer.
  • Online dokumentationssøgning: En dokumentationslæser - CD-baseret, webbaseret eller integreret i applikationen - kan lade brugerne søge i online-dokumentation eller arkiverede publikationer.
  • Søgbare websider: En webbrowser eller proxyserver kan oprette en personlig søgemaskine til indeksering af hver webside, som en bruger har besøgt, så brugerne let kan besøge sider igen.
  • Hjemmesøgning: Et CGI-program kan lade brugerne søge på dit websted.
  • Indholdssøgning: En applikation kan lade brugeren søge i gemte dokumenter efter specifikt indhold; dette kunne integreres i dialogboksen Åbn dokument.
  • Versionskontrol og indholdsstyring: Et dokumentstyringssystem kunne indeksere dokumenter eller dokumentversioner, så de let kan hentes.
  • Nyheder og trådtjenester feeds: En nyhedsserver eller et relæ kan indeksere artikler, når de ankommer.

Selvfølgelig kunne mange søgemaskiner udføre de fleste af disse funktioner, men få open source-søgeværktøjer tilbyder Lucenes brugervenlighed, hurtige implementering og fleksibilitet.

Jeg brugte først Lucene, da jeg udviklede Eyebrowser, et open source Java-baseret værktøj til katalogisering og gennemsyn af postlister. (Se ressourcer for et link.) Et grundlæggende krav til Eyebrowse var fleksibel beskedssøgning og hentningskapacitet. Det krævede en indekserings- og søgekomponent, der effektivt kunne opdatere indeksbasen, når nye beskeder ankom, tillade flere brugere at søge og opdatere indeksbasen samtidigt og skalere til arkiver, der indeholder millioner af meddelelser.

Alle andre open source-søgemaskiner, jeg evaluerede, inklusive Swish-E, Glimpse, iSearch og libibex, var dårligt egnet til Eyebrowses krav på en eller anden måde. Dette ville have gjort integrationen problematisk og / eller tidskrævende. Med Lucene tilføjede jeg indeksering og søgning til Eyebrowser på lidt mere end en halv dag, fra første download til fuldt fungerende kode! Dette var mindre end en tiendedel af den udviklingstid, jeg havde budgetteret, og gav et mere tæt integreret og funktionsrige resultat end noget andet søgeværktøj, jeg overvejede.

Hvordan søgemaskiner fungerer

Oprettelse og vedligeholdelse af en omvendt indeks er det centrale problem i opbygningen af ​​en effektiv søgeordsmotor. For at indeksere et dokument skal du først scanne det for at fremstille en liste over opslag. Indlæg beskriver forekomster af et ord i et dokument; de inkluderer generelt ordet, et dokument-id og muligvis placeringen eller frekvensen af ​​ordet i dokumentet.

Hvis du tænker på indlæggene som formularer , vil et sæt dokumenter give en liste over indlæg sorteret efter dokument-ID. Men for effektivt at finde dokumenter, der indeholder bestemte ord, skal du i stedet sortere posteringerne efter ord (eller efter både ord og dokument, hvilket gør søgninger i flere ord hurtigere). I denne forstand er opbygning af et søgeindeks grundlæggende et sorteringsproblem. Søgeindekset er en liste over indlæg sorteret efter ord.

En innovativ implementering

De fleste søgemaskiner bruger B-træer til at opretholde indekset; de er relativt stabile med hensyn til indsættelse og har velopførte I / O-egenskaber (opslag og indsættelse er O (log n) -operationer). Lucene tager en lidt anden tilgang: snarere end at opretholde et enkelt indeks, bygger det flere indekssegmenter og fletter dem med jævne mellemrum. For hvert nyt dokument indekseret opretter Lucene et nyt indekssegment, men det fletter hurtigt små segmenter med større - dette holder det samlede antal segmenter lille, så søgninger forbliver hurtige. For at optimere indekset til hurtig søgning kan Lucene flette alle segmenterne til et, hvilket er nyttigt til sjældent opdaterede indekser. For at forhindre konflikter (eller låse overhead) mellem indekslæsere og forfattere ændrer Lucene aldrig segmenter på plads, det skaber kun nye. Ved sammenlægning af segmenter skriver Lucene et nyt segment og sletter de gamle - efter at eventuelle aktive læsere har lukket det. Denne tilgang skalerer godt, giver udvikleren en høj grad af fleksibilitet i handel med indekseringshastighed til søgehastighed og har ønskelige I / O-egenskaber til både fletning og søgning.

Et Lucene-indekssegment består af flere filer:

  • Et ordbogindeks, der indeholder en post for hver 100 poster i ordbogen
  • En ordbog, der indeholder en post for hvert unikke ord
  • En posteringsfil, der indeholder en post for hver bogføring

Da Lucene aldrig opdaterer segmenter på plads, kan de gemmes i flade filer i stedet for komplicerede B-træer. For hurtig hentning indeholder ordbogindekset forskydninger i ordbogsfilen, og ordbogen holder forskydninger i bogføringsfilen. Lucene implementerer også en række tricks til at komprimere ordbogen og sende filer - og derved reducere disk I / O - uden at pådrage sig betydelige CPU-omkostninger.

Evaluering af søgemaskiner

Andre almindeligt anvendte open source-søgemaskiner inkluderer Swish-E, Glimpse, libibex, freeWAIS og iSearch. Som enhver softwarepakke er hver optimeret til brug i bestemte situationer; det er ofte vanskeligt at implementere disse værktøjer uden for deres tilsigtede domæner. Overvej følgende funktioner, når du vurderer en søgemaskine:

  • Inkrementel versus batch-indeksering: Nogle søgemaskiner understøtter kun batchindeksering; når de opretter et indeks for et sæt dokumenter, bliver det vanskeligt at tilføje nye dokumenter uden at indeksere alle dokumenter igen. Inkrementel indeksering gør det let at tilføje dokumenter til et eksisterende indeks. For nogle applikationer, som dem, der håndterer live datafeeds, er inkrementel indeksering kritisk. Lucene understøtter begge typer indeksering.
  • Data kilder: Mange søgemaskiner kan kun indeksere filer eller websider. Dette handicappede applikationer, hvor indekserede data kommer fra en database, eller hvor der findes flere virtuelle dokumenter i en enkelt fil, såsom et ZIP-arkiv. Lucene giver udviklere mulighed for at levere dokumentet til indeksøren gennem en Snor eller en InputStream, der tillader datakilden at blive abstraheret fra dataene. Med denne tilgang skal udvikleren dog levere de relevante læsere til dataene.
  • Indekseringskontrol: Nogle søgemaskiner kan automatisk gennemgå et katalogtræ eller et websted for at finde dokumenter, der skal indekseres. Selvom dette er praktisk, hvis dine data allerede er gemt på denne måde, giver crawlerbaserede indeksatorer ofte begrænset fleksibilitet til applikationer, der kræver finkornet kontrol over de indekserede dokumenter. Da Lucene primært fungerer i inkrementel tilstand, lader den applikationen finde og hente dokumenter.
  • Filformater: Nogle søgemaskiner kan kun indeksere tekst eller HTML-dokumenter; andre understøtter en filtermekanisme, der tilbyder et simpelt alternativ til indeksering af tekstbehandlingsdokumenter, SGML-dokumenter og andre filformater. Lucene støtter en sådan mekanisme.
  • Mærkning af indhold: Nogle søgemaskiner behandler et dokument som en enkelt strøm af tokens; andre tillader specifikation af flere datafelter i et dokument, såsom "emne", "abstrakt", "forfatter" og "body". Dette tillader semantisk rigere forespørgsler som "forfatter indeholder Hamilton OG legeme indeholder Constitution. "Lucene understøtter tagging af indhold ved at behandle dokumenter som samlinger af felter og understøtter forespørgsler, der specificerer, hvilke felter der skal søges.
  • Stop tekstbehandling: Almindelige ord såsom "a", "og" og "the" tilføjer lidt værdi til et søgeindeks. Men da disse ord er så almindelige, vil katalogisering af dem bidrage væsentligt til indekseringstid og indeksstørrelse. De fleste søgemaskiner indekserer ikke bestemte ord, kaldet stop ord. Nogle bruger en liste over stopord, mens andre vælger stopord statistisk. Lucene håndterer stopord med de mere generelle Analysator mekanisme, der skal beskrives senere, og tilvejebringer StopAnalyzer klasse, som eliminerer stopord fra inputstrømmen.
  • Stemming: Ofte ønsker en bruger en forespørgsel efter et ord, der skal matche andre lignende ord. For eksempel skal en forespørgsel efter "jump" sandsynligvis også matche ordene "jumped", "jumper" eller "jumps". At reducere et ord til dets rodform kaldes stemming. Lucene implementerer endnu ikke stemming, men du kan nemt tilføje et stemmer gennem et mere sofistikeret Analysator klasse.
  • Forespørgsel funktioner: Søgemaskiner understøtter en række forespørgselsfunktioner. Nogle understøtter fulde boolske forespørgsler; andre støtter kun og forespørgsler. Nogle returnerer en "relevans" score for hvert hit. Nogle kan håndtere nærhed eller nærhedsforespørgsler - "søgning efterfulgt af motor "eller" Knicks nær ved Celtics "- andre kan kun søge på enkelte nøgleord. Nogle kan søge i flere indekser på én gang og flette resultaterne for at give en meningsfuld relevansscore. Lucene understøtter en bred vifte af forespørgselfunktioner, inklusive alle dem, der er anført ovenfor. Dog gør Lucene det understøtter ikke den værdifulde forespørgsel om Soundex eller "lyder som".
  • Samtidighed: Kan flere brugere søge i et indeks på samme tid? Kan en bruger søge i et indeks, mens en anden opdaterer det? Lucene giver brugerne mulighed for at søge i et indeks transaktionelt, selvom en anden bruger samtidig opdaterer indekset.
  • Ikke-engelsk support: Mange søgemaskiner antager implicit, at engelsk er målsproget; Dette er tydeligt i områder som stopordlister, stammealgoritmer og brugen af ​​nærhed til at matche sætningsforespørgsler. Som Lucene forbehandler inputstrømmen gennem Analysator klasse leveret af udvikleren, er det muligt at udføre sprogspecifik filtrering.

Selvom det på ingen måde er udtømmende, tilbyder ovenstående liste et udgangspunkt for evaluering af en søgemaskine til et bestemt projekt. Nogle søgeværktøjer passer dårligt til bestemte opgaver - forståelse af applikationens krav kan hjælpe dig med at vælge det rigtige værktøj til jobbet.

Brug af Lucene

Jeg vil illustrere, hvordan man bruger Lucene til at oprette, udfylde og søge i et indeks. Af hensyn til klarheden er importudtalelser og undtagelseshåndtering udeladt fra prøveprogrammerne. I disse illustrationer har jeg gemt søgeindekset i filsystemet (du kan gemme indekser hvor som helst, f.eks. I hukommelsen eller i en database). De filer, der indekseres, er enkle tekstfiler. Med Lucene kan du også nemt indeksere andre dokumentformater og dokumenter, der ikke er gemt i filer.

Opret et indeks

Det enkle program OpretIndex.java opretter et tomt indeks ved at generere et IndexWriter objekt og instruere det om at oprette et tomt indeks. I dette eksempel er navnet på den mappe, der vil gemme indekset, angivet på kommandolinjen.

offentlig klasse CreateIndex {// brug: CreateIndex indeks-katalog offentlig statisk ugyldig hoved (String [] args) kaster Undtagelse {String indexPath = args [0]; IndexWriter-forfatter; // Et indeks oprettes ved at åbne en IndexWriter med // create-argumentet sat til sand. skribent = ny IndexWriter (indexPath, null, true); writer.close (); }} 

Indeks tekstdokumenter

IndexFile.java viser, hvordan du tilføjer dokumenter - filerne navngivet på kommandolinjen - til et indeks. For hver fil IndexFiles skaber en Dokument objekt, derefter opkald IndexWriter.addDocument for at føje det til indekset. Fra Lucenes synspunkt er a Dokument er en samling af felter, der er navn-værdipar. EN Mark kan få sin værdi fra en Snor, for korte felter eller en InputStream, for lange marker. Brug af felter giver dig mulighed for at opdele et dokument i separat søgbare og indekserbare sektioner og knytte metadata - såsom navn, forfatter eller ændringsdato - til et dokument. For eksempel, når du gemmer e-mail-beskeder, kan du placere en meddelelses emne, forfatter, dato og brødtekst i separate felter og derefter oprette semantisk rigere forespørgsler som "emne indeholder Java OG forfatter indeholder Gosling. "I koden nedenfor gemmer vi to felter i hver Dokument: sti, for at identificere den originale filsti, så den kan hentes senere, og legeme, for filens indhold.

offentlig klasse IndexFiles {// brug: IndexFiles indekssti-fil. . . offentlig statisk ugyldigt hoved (String [] args) kaster Undtagelse {String indexPath = args [0]; IndexWriter-forfatter; skribent = ny IndexWriter (indexPath, ny SimpleAnalyzer (), false); for (int i = 1; i