Eine einfache Dateisuche mit Lucene

1. Übersicht

Apache Lucene ist eine Volltextsuchmaschine, die von verschiedenen Programmiersprachen verwendet werden kann. Um mit Lucene zu beginnen, lesen Sie bitte unseren Einführungsartikel hier.

In diesem Artikel schnell, wir Index eine Textdatei und suchen Probe Strings und Textausschnitte in dieser Datei.

2. Maven Setup

Fügen wir zuerst die erforderlichen Abhängigkeiten hinzu:

 org.apache.lucene lucene-core 7.1.0 

Die neueste Version finden Sie hier.

Zum Parsen unserer Suchanfragen benötigen wir außerdem:

 org.apache.lucene lucene-queryparser 7.1.0 

Denken Sie daran, die neueste Version hier zu überprüfen.

3. Dateisystemverzeichnis

Um Dateien zu indizieren, müssen wir zuerst einen Dateisystemindex erstellen.

Lucene stellt die FSDirectory- Klasse zum Erstellen eines Dateisystemindex bereit :

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

Hier ist indexPath der Speicherort des Verzeichnisses. Wenn das Verzeichnis nicht existiert, wird es von Lucene erstellt.

Lucene bietet drei konkrete Implementierungen der abstrakten FSDirectory- Klasse: SimpleFSDirectory, NIOFSDirectory und MMapDirectory. Jeder von ihnen hat möglicherweise spezielle Probleme mit einer bestimmten Umgebung.

Beispielsweise weist SimpleFSDirectory eine schlechte gleichzeitige Leistung auf, da es blockiert, wenn mehrere Threads aus derselben Datei lesen.

In ähnlicher Weise treten bei den Implementierungen von NIOFSDirectory und MMapDirectory Probleme mit dem Dateikanal in Windows- bzw. Speicherfreigabeproblemen auf.

Um solche Umwelteigenschaften zu überwinden, stellt Lucene die Methode FSDirectory.open () zur Verfügung. Beim Aufrufen wird versucht, je nach Umgebung die beste Implementierung auszuwählen.

4. Indextextdatei

Nachdem wir das Indexverzeichnis erstellt haben, fügen wir dem Index eine Datei hinzu:

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(); }

Hier erstellen wir ein Dokument mit zwei StringFields mit den Namen "Pfad" und "Dateiname" und einem TextField mit dem Namen "Inhalt".

Beachten Sie, dass wir die fileReader- Instanz als zweiten Parameter an TextField übergeben . Das Dokument wird mit dem IndexWriter zum Index hinzugefügt.

Das dritte Argument im TextField- oder StringField- Konstruktor gibt an, ob der Wert des Felds ebenfalls gespeichert wird.

Schließlich rufen wir close () des IndexWriter auf, um die Sperre ordnungsgemäß zu schließen und aus den Indexdateien zu entfernen .

5. Indizierte Dateien durchsuchen

Lassen Sie uns nun die Dateien durchsuchen, die wir indiziert haben:

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()); }

Testen wir nun die Funktionalität:

@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")); }

Beachten Sie, wie wir einen Dateisystemindex im Speicherort indexPath erstellen und die Datei1.txt indizieren.

Dann suchen wir einfach im Feld "Inhalt" nach dem String " consectetur " .

6. Fazit

Dieser Artikel war eine kurze Demonstration der Indizierung und Suche von Text mit Apache Lucene. Weitere Informationen zum Indizieren, Anbrennen und Abfragen von Lucene finden Sie in unserer Einführung zum Lucene-Artikel.

Wie immer ist der Code für die Beispiele auf Github zu finden.