Простой поиск файлов с помощью Lucene
1. обзор
Apache Lucene - это механизм полнотекстового поиска, который может использоваться различными языками программирования. Чтобы начать работу с Lucene, обратитесь к нашему вводномуarticle here.
В этой быстрой статье мы проиндексируем текстовый файл и найдем образецStrings и текстовые фрагменты в этом файле.
2. Maven Setup
3. Каталог файловой системы
Чтобы индексировать файлы, нам сначала нужно создать индекс файловой системы.
Lucene предоставляет классFSDirectory для создания индекса файловой системы:
Directory directory = FSDirectory.open(Paths.get(indexPath));
ЗдесьindexPath - это расположение каталога. If the directory doesn’t exist, Lucene will create it.
Lucene предоставляет три конкретные реализации абстрактного классаFSDirectory:SimpleFSDirectory, NIOFSDirectory, and MMapDirectory. У каждой из них могут быть особые проблемы с данной средой.
Например,SimpleFSDirectory has poor concurrent performance as it blocks when multiple threads read from the same file.
АналогичноNIOFSDirectory and MMapDirectory implementations face file-channel issues in Windows and memory release problems respectively.
To overcome such environment peculiarities Lucene provides the FSDirectory.open() method. При вызове пытается выбрать лучшую реализацию в зависимости от среды.
4. Индексный текстовый файл
После того, как мы создали каталог индекса, давайте продолжим и добавим файл в индекс:
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();
}
Здесь мы создаем документ с двумяStringFieldsс именами «путь» и «имя файла» иTextFieldс именами «содержимое».
Обратите внимание, что мы передаем экземплярfileReader в качестве второго параметраTextField. Документ добавляется в индекс с помощьюIndexWriter.
Третий аргумент в конструктореTextField илиStringField указывает, будет ли также сохранено значение поля.
Наконец, мы вызываемclose()IndexWriter, чтобы корректно закрыть и снять блокировку с индексных файлов.
5. Поиск по проиндексированным файлам
Теперь поищем в индексированных файлах:
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());
}
Давайте теперь проверим функциональность:
@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"));
}
Обратите внимание, как мы создаем индекс файловой системы в местоположенииindexPath и индексируемfile1.txt.
Затем мы просто ищемString «consectetur» в поле“contents”.
6. Заключение
Эта статья была быстрой демонстрацией индексации и поиска текста с помощью Apache Lucene. Чтобы узнать больше об индексировании, поиске и запросах Lucene, обратитесь к нашемуintroduction to Lucene article.
Как всегда, код примеров можно найтиover on Github.