2010-11-03 10 views

risposta

33

Lucene è piuttosto un grande argomento con un sacco di classi e metodi per coprire, e che normalmente non può utilizzare senza comprensione a almeno alcuni concetti di base. Se hai bisogno di un servizio rapidamente disponibile, usa invece Solr. Se hai bisogno del pieno controllo di Lucene, continua a leggere. Tratterò alcuni concetti e classi chiave di Lucene, che li rappresentano. (Per informazioni su come leggere i file di testo nella memoria, ad esempio, articolo this).

Qualsiasi cosa tu voglia fare in Lucene - indicizzazione o ricerca - hai bisogno di un analizzatore. L'obiettivo dell'analizzatore è di tokenizzare (irrompere nelle parole) e arginare (ottenere una base di una parola) il testo di input. Inoltre getta le parole più frequenti come "a", "il", ecc. È possibile trovare gli analizzatori per più di 20 lingue, oppure è possibile utilizzare SnowballAnalyzer e passare la lingua come parametro.
Per creare un'istanza di SnowballAnalyzer per l'inglese questo:

Analyzer analyzer = new SnowballAnalyzer(Version.LUCENE_30, "English"); 

Se avete intenzione di testi di indice in diverse lingue, e desidera selezionare automaticamente analizzatore, è possibile utilizzare tika's LanguageIdentifier.

È necessario memorizzare l'indice da qualche parte. Ci sono 2 possibilità principali per questo: indice in memoria, che è facile da provare, e indice del disco, che è il più diffuso.
Utilizzare uno dei prossimi 2 linee:

Directory directory = new RAMDirectory(); // RAM index storage 
Directory directory = FSDirectory.open(new File("/path/to/index")); // disk index storage 

Quando si desidera aggiungere, aggiornare o cancellare i documenti, è necessario IndexWriter:

IndexWriter writer = new IndexWriter(directory, analyzer, true, new IndexWriter.MaxFieldLength(25000)); 

Qualsiasi documento (file di testo nel tuo caso) è un set di campi. Per creare il documento, che conterrà informazioni sul file, utilizzare questo:

Document doc = new Document(); 
String title = nameOfYourFile; 
doc.add(new Field("title", title, Field.Store.YES, Field.Index.ANALYZED)); // adding title field 
String content = contentsOfYourFile; 
doc.add(new Field("content", content, Field.Store.YES, Field.Index.ANALYZED)); // adding content field 
writer.addDocument(doc); // writing new document to the index 

Field costruttore prende il nome di campo, è il testo e almeno 2 più parametri. La prima è una bandiera, che mostra se Lucene deve conservare questo campo. Se è uguale a Field.Store.YES, avrai la possibilità di recuperare tutto il tuo testo dall'indice, altrimenti verranno memorizzate solo le informazioni dell'indice su di esso.
Secondo parametro indica se Lucene deve indicizzare questo campo oppure no. Utilizzare Field.Index.ANALYZED per qualsiasi campo su cui si sta effettuando la ricerca.
Normalmente, si usano entrambi i parametri come mostrato sopra.

Non dimenticare di chiudere il IndexWriter dopo il lavoro è fatto:

writer.close(); 

ricerca è un po 'complicato. Avrete bisogno di diverse classi: Query e QueryParser per fare domanda Lucene dalla stringa, IndexSearcher per la ricerca vera e propria, TopScoreDocCollector per memorizzare i risultati (si passa alla IndexSearcher come parametro) e ScoreDoc per scorrere i risultati. Successivo frammento di codice mostra come tutto questo è composto da:

IndexSearcher searcher = new IndexSearcher(directory); 
QueryParser parser = new QueryParser(Version.LUCENE_30, "content", analyzer); 
Query query = parser.parse("terms to search"); 
TopScoreDocCollector collector = TopScoreDocCollector.create(HOW_MANY_RESULTS_TO_COLLECT, true); 
searcher.search(query, collector); 

ScoreDoc[] hits = collector.topDocs().scoreDocs; 
// `i` is just a number of document in Lucene. Note, that this number may change after document deletion 
for (int i = 0; i < hits.length; i++) { 
    Document hitDoc = searcher.doc(hits[i].doc); // getting actual document 
    System.out.println("Title: " + hitDoc.get("title")); 
    System.out.println("Content: " + hitDoc.get("content")); 
    System.out.println(); 
} 

Nota secondo argomento al costruttore QueryParser - è campo di default, vale a dire di campo che verrà cercato se non di qualificazione è stato dato. Ad esempio, se la tua query è "title: term", Lucene cercherà una parola "term" nel campo "title" di tutti i documenti, ma se la tua query è solo "term" se cercherà nel campo predefinito, in questo caso - "contenuti". Per maggiori informazioni vedi Lucene Query Syntax.
QueryParser prende anche l'analizzatore come ultimo argomento. Questo deve essere lo stesso analizzatore usato per indicizzare il testo.

L'ultima cosa che devi sapere è un primo parametro TopScoreDocCollector.create. È solo un numero che rappresenta il numero di risultati che desideri raccogliere. Ad esempio, se è uguale a 100, Lucene raccoglierà solo i primi (per punteggio) 100 risultati e lascerà cadere il resto. Questo è solo un atto di ottimizzazione: raccogli i risultati migliori e, se non sei soddisfatto, ripeti la ricerca con un numero maggiore.

Infine, non dimenticare di chiudere ricercatore e la directory di risorse di sistema non sciolti:

searcher.close(); 
directory.close(); 

EDIT: vedere anche IndexFiles demo class da Lucene 3.0 sources.

+0

ho provato questo http://pastebin.com/HqrbBPtp, ma senza successo ... – celsowm

+0

Nella riga 80 hai: 'QueryParser parser = new QueryParser (Version.LUCENE_30," computer ", analizzatore);', cioè si imposta il secondo parametro (campo predefinito) su "computer", quindi si esegue una ricerca senza qualificatore. Lucene cerca di usare _field_ "computer" predefinito per trovare _term_ "computer", e poiché il tuo documento non ha questo campo, Lucene fallisce. Utilizzare 'parser QueryParser = new QueryParser (Version.LUCENE_30," content ", analyzer);' oppure cercare con qualificatore: 'Query query = parser.parse (" content: computer ");'. – ffriend

3
package org.test; 

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileReader; 
import java.io.IOException; 


import org.apache.lucene.queryParser.*; 
import org.apache.lucene.search.IndexSearcher; 
import org.apache.lucene.search.Query; 
import org.apache.lucene.search.ScoreDoc; 
import org.apache.lucene.search.TopScoreDocCollector; 
import org.apache.lucene.store.Directory; 
import org.apache.lucene.store.FSDirectory; 
import org.apache.lucene.store.LockObtainFailedException; 
import org.apache.lucene.analysis.standard.StandardAnalyzer; 
import org.apache.lucene.index.CorruptIndexException; 
import org.apache.lucene.index.IndexWriter; 
import org.apache.lucene.store.RAMDirectory; 
import org.apache.lucene.util.Version; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 

public class LuceneSimple { 

private static void addDoc(IndexWriter w, String value) throws IOException { 
    Document doc = new Document(); 
    doc.add(new Field("title", value, Field.Store.YES, Field.Index.ANALYZED)); 
    w.addDocument(doc); 
} 



public static void main(String[] args) throws CorruptIndexException, LockObtainFailedException, IOException, ParseException { 

    File dir = new File("F:/tmp/dir"); 

    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); 

    Directory index = new RAMDirectory(); 
    //Directory index = FSDirectory.open(new File("lucDirHello")); 


    IndexWriter w = new IndexWriter(index, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED); 

    w.setRAMBufferSizeMB(200); 

    System.out.println(index.getClass() + " RamBuff:" + w.getRAMBufferSizeMB()); 

    addDoc(w, "Lucene in Action"); 
    addDoc(w, "Lucene for Dummies"); 
    addDoc(w, "Managing Gigabytes"); 
    addDoc(w, "The Art of Computer Science"); 
    addDoc(w, "Computer Science ! what is that ?"); 


    Long N = 0l; 

    for(File f : dir.listFiles()){ 
     BufferedReader br = new BufferedReader(new FileReader(f)); 
     String line = null; 
     while((line = br.readLine()) != null){ 
     if(line.length() < 140) continue;  
     addDoc(w, line); 
     ++N; 
     } 
     br.close(); 
    } 

    w.close(); 

    // 2. query 
    String querystr = "Computer"; 

    Query q = new QueryParser(Version.LUCENE_30, "title", analyzer).parse(querystr); 


    //search 
    int hitsPerPage = 10; 

    IndexSearcher searcher = new IndexSearcher(index, true); 

    TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); 

    searcher.search(q, collector); 

    ScoreDoc[] hits = collector.topDocs().scoreDocs; 

    System.out.println("Found " + hits.length + " hits."); 
    for(int i=0;i<hits.length;++i) { 
     int docId = hits[i].doc; 
     Document d = searcher.doc(docId); 
     System.out.println((i + 1) + ". " + d.get("title")); 
    } 


    searcher.close(); 

} 

} 
+0

è possibile impostare la variabile "File dir" nella directory che è necessario indicizzare. – smartnut007

Problemi correlati