Лесно търсене на файлове с Lucene

1. Общ преглед

Apache Lucene е пълнотекстова търсачка, която може да се използва от различни езици за програмиране. За да започнете с Lucene, вижте нашата уводна статия тук.

В тази бърза статия ще индексираме текстов файл и ще потърсим примерни низове и текстови фрагменти в този файл.

2. Настройка на Maven

Нека първо добавим необходимите зависимости:

 org.apache.lucene lucene-core 7.1.0 

Най-новата версия можете да намерите тук.

Също така, за да анализираме нашите заявки за търсене, ще ни трябва:

 org.apache.lucene lucene-queryparser 7.1.0 

Не забравяйте да проверите най-новата версия тук.

3. Директория на файловата система

За да индексираме файлове, първо ще трябва да създадем индекс на файлова система.

Lucene предоставя клас FSDirectory за създаване на индекс на файлова система:

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

Тук indexPath е местоположението на директорията. Ако директорията не съществува, Lucene ще я създаде.

Lucene осигурява три конкретни реализации на абстрактни FSDirectory класа: SimpleFSDirectory, NIOFSDirectory и MMapDirectory. Всеки от тях може да има специални проблеми с дадена среда.

Например SimpleFSDirectory има лоша едновременна производителност, тъй като блокира, когато множество нишки четат от един и същ файл.

По подобен начин изпълненията на NIOFSDirectory и MMapDirectory са изправени съответно пред проблеми с файловите канали в Windows и паметта.

За да се преодолеят такива особености на средата, Lucene предоставя метода FSDirectory.open () . При извикване той се опитва да избере най-доброто изпълнение в зависимост от средата.

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.

След това просто търсим Stringconsectetur ” в полето “съдържание” .

6. Заключение

Тази статия представлява бърза демонстрация на индексиране и търсене на текст с Apache Lucene. За да научите повече за индексирането, запаметяването и заявките за Lucene, моля, вижте нашето въведение в статията за Lucene

Както винаги кодът за примерите може да бъде намерен в Github.