Материал по работе с Apache Lucene и созданию простейшего нечёткого поиска

от автора

Пост расчитан на начинающих, на людей незнакомых с технологией Apache Lucene. В нем нет материала о том, как устроен Apache Lucene внутри, какие алгоритмы, структуры данных и методы использовались для создания фреймворка. Пост является обучающим материалом-тизером, написанным для того, чтобы показать как организовать простейший нечёткий поиск тексту. В качестве материала для обучения предоставлен код на github, сам пост в качестве документации и немного данных для тестирования поисковых запросов.

Введение

Будем считать что рассказывать что же такое Apache Lucene не нужно, раз читатель заинтересовался этой технологией. Подробно об этом написано здесь и здесь. В статье будут встречаться такие термины как: запрос, индексация, анализатор, нечеткие совпадения, токены, документы. Советую сначала прочитать вот эту статью. В ней эти термины описывают в контексте фреймворка Elasticsearch, который базируется на библиотеках Apache Lucene. Поэтому базовая терминология и определения совпадают.

Инструментарий

В статье описывается использование Apache Lucene 5.4.1. Исходный код доступен на github, в репозитории есть небольшой набор данных для тестирования. По сути статья является подробной документацией к коду в репозитории. Начать «играть» с проектом можно с запуска тестов в классе BasicSearchExamplesTest.

Создание индексов

Проиндексировать документы можно с помощью класса MessageIndexer. В нём есть метод index:

    public void index(final Boolean create, List<Document> documents) throws IOException {         final Analyzer analyzer = new RussianAnalyzer();         index(create, documents, analyzer);     } 

Он принимает на вход пременную create и documents. Переменная create отвечает за поведение индексатора. Если она равна true, то индексатор будет создавать новый индекс даже если индекс уже существовал. Если false, то индекс будет обновлятся.
Переменная documents это список объектов Document. Document это объект индексации и поиска. Он представляет собой набор полей, каждое поде имеет имя и текстовое значение. Для того чтобы получить список документов создан класс MessageToDocument. Его задача создавать Document используя два строковых поля: body и title.

    public static Document createWith(final String titleStr, final String bodyStr) {         final Document document = new Document();          final FieldType textIndexedType = new FieldType();         textIndexedType.setStored(true);         textIndexedType.setIndexOptions(IndexOptions.DOCS);         textIndexedType.setTokenized(true);          //index title         Field title = new Field("title", titleStr, textIndexedType);         //index body         Field body = new Field("body", bodyStr, textIndexedType);          document.add(title);         document.add(body);         return document;     } 

Обратите внимание что метод index по умолчанию использует RussianAnalyzer, доступный в библиотеке lucene-analyzers-common.

Для того чтобы поиграть с созданием индекса перейдите к классу MessageIndexerTest.

Поиск

Для демонстрации базовых возможностей поиска создан класс BasicSearchExamples. В нём реализованы два метода поиска: простой поиск по токенам и нечеткий поиск. За простой поиск отвечают методы searchIndexWithTermQuery() и searchInBody(), за нечеткий поиск метод fuzzySearch().

В Lucene существует много способов создать запрос, но для простоты методы обычного поиска реализованы только с помощью классов QueryParser и TermQuery. Методы нечеткого поиска используют FuzzyQuery, которая зависит от одного важного параметра: maxEdits. Этот параметр отвечает за нечеткость поиска, подробности здесь. Погрузиться в многообразие способов сделать запрос можно здесь.

Для того чтобы поиграть с поиском перейдите к классу BasicSearchExamplesTest

Задание

Чтобы играть с проектом было не скучно попробуйте выполнить несколько заданий:

  • Сделайте интерактивный консольный поиск. Поиск должен показывать выдачу и спрашивать следующий запрос.
  • Сейчас поиск работает только с полем body. Сделайте так, чтобы поиск работал по полям title и body одновременно.
  • Подсчитайте количество проиндексированных слов (токенов)
  • Посмотрите на класс запросов MoreLikeThisQuery. Попробуйте сгруппировать все документы по похожести используя значение score.

Заключение

Преимущество Apache Lucene в его простоте, высокой скорости работы и низких требованиях к ресурсам. Недостаток в отсутствии хорошей документации, особенно на русском языке. Проект очень быстро развивается, поэтому книги, туториалы и Q/A, которыми забит интернет, давно потеряли актуальность. К примеру у меня ушло 4-5 дней только на то, чтобы понять как вытащить из индексов Lucene векторы TF-IDF. Надеюсь что этот пост привлёчет внимание специалистов к этой проблеме недостатка информации.

Для тех же кто хочет погрузиться в мир Apache Lucene советую взглянуть на документацию Elasticsearch. Многие вещи там очень хорошо описаны, со ссылками на авторитетные источники и с примерами.

ссылка на оригинал статьи https://habrahabr.ru/post/277509/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *