Una semplice ricerca di file con Lucene

1. Panoramica

Apache Lucene è un motore di ricerca full-text, che può essere utilizzato da vari linguaggi di programmazione. Per iniziare con Lucene, fare riferimento al nostro articolo introduttivo qui.

In questo rapido articolo, indicizzeremo un file di testo e cercheremo stringhe di esempio e frammenti di testo all'interno di quel file.

2. Installazione di Maven

Aggiungiamo prima le dipendenze necessarie:

 org.apache.lucene lucene-core 7.1.0 

L'ultima versione può essere trovata qui.

Inoltre, per analizzare le nostre query di ricerca, avremo bisogno di:

 org.apache.lucene lucene-queryparser 7.1.0 

Ricordati di controllare l'ultima versione qui.

3. Directory del file system

Per indicizzare i file, dobbiamo prima creare un indice del file system.

Lucene fornisce la classe FSDirectory per creare un indice del file system:

Directory directory = FSDirectory.open(Paths.get(indexPath));

Qui indexPath è la posizione della directory. Se la directory non esiste, Lucene la creerà.

Lucene fornisce tre implementazioni concrete della classe astratta FSDirectory : SimpleFSDirectory, NIOFSDirectory e MMapDirectory. Ognuno di loro potrebbe avere problemi speciali con un determinato ambiente.

Ad esempio, SimpleFSDirectory ha scarse prestazioni simultanee poiché si blocca quando più thread leggono dallo stesso file.

Allo stesso modo, le implementazioni NIOFSDirectory e MMapDirectory affrontano rispettivamente problemi di canale file in Windows e problemi di rilascio della memoria.

Per superare queste peculiarità ambientali Lucene fornisce il metodo FSDirectory.open () . Quando viene richiamato, cerca di scegliere la migliore implementazione a seconda dell'ambiente.

4. File di testo indice

Una volta creata la directory index, andiamo avanti e aggiungiamo un file all'indice:

public void addFileToIndex(String filepath) { Path path = Paths.get(filepath); File file = path.toFile(); IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); Directory indexDirectory = FSDirectory .open(Paths.get(indexPath)); IndexWriter indexWriter = new IndexWriter( indexDirectory, indexWriterConfig); Document document = new Document(); FileReader fileReader = new FileReader(file); document.add( new TextField("contents", fileReader)); document.add( new StringField("path", file.getPath(), Field.Store.YES)); document.add( new StringField("filename", file.getName(), Field.Store.YES)); indexWriter.addDocument(document); indexWriter.close(); }

Qui creiamo un documento con due StringField denominati "path" e "filename" e un TextField chiamato "content".

Nota che passiamo l' istanza fileReader come secondo parametro a TextField . Il documento viene aggiunto all'indice utilizzando IndexWriter.

Il terzo argomento nel costruttore TextField o StringField indica se verrà archiviato anche il valore del campo.

Infine, invochiamo close () di IndexWriter per chiudere e rilasciare con grazia il blocco dai file di indice.

5. Cerca file indicizzati

Ora cerchiamo i file che abbiamo indicizzato:

public List searchFiles(String inField, String queryString) { Query query = new QueryParser(inField, analyzer) .parse(queryString); Directory indexDirectory = FSDirectory .open(Paths.get(indexPath)); IndexReader indexReader = DirectoryReader .open(indexDirectory); IndexSearcher searcher = new IndexSearcher(indexReader); TopDocs topDocs = searcher.search(query, 10); return topDocs.scoreDocs.stream() .map(scoreDoc -> searcher.doc(scoreDoc.doc)) .collect(Collectors.toList()); }

Proviamo ora la funzionalità:

@Test public void givenSearchQueryWhenFetchedFileNamehenCorrect(){ String indexPath = "/tmp/index"; String dataPath = "/tmp/data/file1.txt"; Directory directory = FSDirectory .open(Paths.get(indexPath)); LuceneFileSearch luceneFileSearch = new LuceneFileSearch(directory, new StandardAnalyzer()); luceneFileSearch.addFileToIndex(dataPath); List docs = luceneFileSearch .searchFiles("contents", "consectetur"); assertEquals("file1.txt", docs.get(0).get("filename")); }

Notare come stiamo creando un indice del file system nella posizione indexPath e indicizzando il file1.txt.

Quindi, cerchiamo semplicemente la stringa " consectetur " nel campo "contenuto" .

6. Conclusione

Questo articolo è stata una rapida dimostrazione di indicizzazione e ricerca di testo con Apache Lucene. Per ulteriori informazioni sull'indicizzazione, la masterizzazione e le query di Lucene, fare riferimento alla nostra introduzione all'articolo su Lucene.

Come sempre il codice per gli esempi può essere trovato su Github.