Lucene è un progetto Apache Jakarta, che mette a disposizione un insieme di API scritte in Java, funzionali all'implementazione di potenti (efficienti ed altamente scalabili) motori di ricerca full-text per applicazioni J2EE.
La ricerca full-text si pone come obiettivo quello di render possibile all'utente di ricercare quanto desiderato fornendo esclusivamente una chiave di ricerca, talvolta quest'ultima può essere anche molto generica. Esempi famosi di motori di ricerca full-text sono Yahoo! e Google, grazie ai quali il mondo web ad oggi è interrogabile nonostante la sua complessità e vastità.
L'esempio appena fatto, però, non deve far pensare che solo particolari tipi di applicazioni richiedano (nella fattispecie, quelle Web) una ricerca di tipo full-text, infatti un controesempio altrettanto famoso potrebbe essere Google Desktop, il quale fornisce capacità di ricerca full-text all'utenza di un sistema operativo rispetto ai dati immagazzinati sulla macchina locale.
Il complesso delle API messe a disposizione dal core di Lucene consente di implementare funzionalità di indicizzazione rispetto a diversi formati di documento (PDF, HTML, documenti Office, documenti di testo semplice, etc.) e rispetto ad informazioni direttamente estrapolate da un database.
Il risultato dell'indicizzazione, come è lecito attendersi, è un indice di Lucene interrogabile in fase di ricerca mediante delle query. Le query di Lucene rispettano una logica ben definita (in questo articolo introduttivo non sarà approfondita) che è del tutto filtrata all'utente dal momento che a quest'ultimo è richiesta soltanto una chiave di ricerca rispetto alla quale interrogare l'indice precostituito.
Il risultato di una generica ricerca su di un indice di Lucene è una lista di documenti, precedentemente indicizzati, che contengono una o più parole costituenti la keyword di ricerca. Ad ogni documento restituito è assegnato anche uno score (punteggio) che indica all'utente quanto affine sia il documento in questione rispetto alla chiave di ricerca fornita.
L'indicizzazione con Lucene
L'indice, frutto del processo di indicizzazione, è composto da un insieme di Document di Lucene. Un Document è, a sua volta, una composizione di Field che sono delle coppie <nome, valore>
che caratterizzano e contengono l'informazione mantenuta.
Se vogliamo cercare un'analogia con un'altra tecnica di immagazzinamento delle informazioni, possiamo assimilare un documento ad un record di una base di dati, dal momento che anche quest'ultimo è una composizione di campi (contenenti dei valori) con dei nomi ben definiti. Ad esempio, un generico file di testo stipato sul disco rigido può essere reso a Lucene mediante anche solo un unico Field
che ne caratterizza il contenuto, ciò qualora nessuna informazione aggiuntiva fosse necessaria.
Document
e Field
sono solo due delle principali classi che Lucene mette a disposizione per il processo di indicizzazione. Infatti, IndexWriter ed Analyzer sono altrettante classi che collaborano per far sì che il documento venga opportunamente reso, a seguito di un'analisi, prima di essere immagazzinato come riferimento dell'indice. In particolare l'Analyzer si occupa delle elaborazioni da effettuare sul documento che gli viene passato dall'IndexWriter
, mentre quest'ultimo si occupa dell'effettiva scrittura del documento nell'indice e della gestione delle ottimizzazioni. La tabella che segue mostra sinteticamente i compiti delle principali classi precedentemente citate.
Classe | Descrizione |
---|---|
IndexWriter |
crea l'indice, inserisce documenti nell'indice e ottimizza quest'ultimo |
Analyzer |
compie elaborazioni sul testo: eliminazione di parole ricorrenti e resa del testo come insieme di token |
Document |
rappresenta una singola unità d'informazione ed è il modo logico con cui Lucene organizza, appunto, le informazioni |
Field |
specifica una particolare informazione all'interno del documento, concorre a realizzare l'informazione complessiva |
Directory |
Fornisce una rappresentazione logica di un indice realizzato dalle API di Lucene |
La ricerca con Lucene
Per effettuare una ricerca su di un indice precostituito è necessario aprire l'indice in questione mediante un IndexSearcher. L'IndexSearcher
acquisirà la risorsa indice per poter, in seguito, effettuare le ricerche desiderate mediante delle opportune Query.
La Query in Lucene è una perfetta astrazione del concetto classico di query per il recupero di informazioni da un supporto persistente; tale estrazione a sua volta è fornita da un QueryParser
. Il QueryParser
ha l'obiettivo di acquisire la keyword di ricerca (una o più parole, anche generiche), analizzare quest'ultima con il medesimo Analyzer
usato per la creazione dell'indice ed infine rendere la stringa di ricerca una query che rispetti predeterminate regole; l'ultimo passo restituisce l'oggetto Query
che sarà passato all'IndexSearcher
per poter effettuare la ricerca sull'indice ed immagazzinare i risultati di tale ricerca, con relativi score, all'interno di un oggetto Hits
. In Tab. 2 si illustrano sinteticamente i compiti delle principali classi citate.
Classe | Descrizione |
---|---|
IndexSearcher |
apre l'indice precedentemente creato, effettua la query su di esso |
Query |
rappresenta una query costituita in fase di elaborazione della keyword |
QueryParser |
interpreta la keyword fornita dall'utente e la trasforma in una query di Lucene |
Hits |
contiene i risultati (documenti con relativo score) della ricerca effettuata sull'indice di Lucene |
La ricerca di Lucene prevede altre modalità operative oltre a quella descritta precedentemente la cui descrizione però esula dallo scopo introduttivo di questo articolo.
Conclusioni
Lucene fornisce la possibilità di implementare motori di ricerca full-text mediante l'implementazione di meccanismi di indicizzazione e di ricerca, così come presentati. Le API, al core della libreria scritta in Java, facilitano i compiti implementativi grazie alla logica con la quale esse sono organizzate: ogni API dipende da qualche altra che svolge una particolare porzione di elaborazione rispetto alla elaborazione complessivamente necessaria.