Статьи

Как выполнить нечеткое сопоставление с Mongo Connector и ElasticSearch

Люк Ловетт, инженер Python в MongoDB

Вступление

Предположим, вы работаете с MongoDB. Большой! Теперь вы можете найти точные совпадения со всеми запросами, которые вы можете бросить в базу данных. Теперь представьте, что вы также встраиваете функцию текстового поиска в свое приложение. Он должен рисовать слова из шума с ошибками, и результаты могут совпадать и с синонимами! Для этой сложной задачи вы выбрали один из проектов на основе Lucene, Elasticsearch или Solr . Но теперь у вас есть проблема — как этот инструмент будет искать ваши документы, хранящиеся в MongoDB? И как вы будете обновлять содержимое поисковой системы?

Mongo Connector заполняет пробел между MongoDB и некоторыми лучшими инструментами поиска, такими как Elasticsearch и Solr. Он не только способен экспортировать данные из набора реплик MongoDB или сегментированного кластера в эти системы, но также поддерживает согласованность данных между этими системами: при вставке, обновлении и удалении документов в MongoDB эти изменения вскоре отражаются на других сторона через разъем Монго. Вы даже можете использовать Mongo Connector для потоковой передачи изменений, выполненных на одной первичной реплике, в другую, имитируя кластер с несколькими хозяевами.

Когда Mongo Connector увидел свой первый выпуск в августе 2012 года, он был очень прост в своих возможностях и не обладал отказоустойчивостью. Я работаю над Mongo Connector с ноября 2013 года с помощью команды MongoDB Python, и я рад сообщить, что Mongo Connector прошел большой путь с точки зрения предоставляемых им функций и (особенно) стабильности. В этом посте будут показаны некоторые из этих новых функций и приведен пример того, как реплицировать операции из MongoDB в Elasticsearch, поисковую систему с открытым исходным кодом, используя Mongo Connector. В конце этого поста мы сможем выполнять текстовые запросы с нечетким соответствием для потоков данных в Elasticsearch.

Получение нашего набора данных

Для этого поста мы будем публиковать посты с популярного сайта агрегации ссылок Reddit. Недавно мы добавили безопасное кодирование типов данных, поддерживаемых MongoDB (т. Е. Типов BSON), к типам, которые могут обрабатывать внешние драйверы баз данных (в данном случае , asticsearch-py ). Это делает безопасным использование для репликации документов, содержание которых мы не можем контролировать (например, с помощью веб-скрапинга). Используя этот скрипт, который извлекает новые сообщения из reddit , мы будем транслировать новые сообщения Reddit в MongoDB:

./reddit2mongo --mongo-host localhost --mongo-port 27017

По мере обработки сообщения вы должны увидеть первые 20 символов заголовка. Это (я допускаю, медленно, благодаря ограничениям Reddit API) эмулирует вставки в MongoDB, которые делает ваше приложение.

Разжигание соединителя

Далее мы запустим Mongo Connector. Чтобы загрузить и установить Mongo Connector, вы можете использовать pip:

pip install mongo-connector

Для этой демонстрации мы предполагаем, что Elasticsearch уже настроен и запущен на локальном компьютере и прослушивает порт 9200. Вы можете начать репликацию из MongoDB в Elasticsearch с помощью следующей команды:

mongo-connector -m localhost:27017 -t localhost:9200 -d mongo_connector/doc_managers/elastic_doc_manager.py

Конечно, если мы хотим выполнять текстовый поиск только по заголовкам и тексту постов, мы можем ограничить то, через какие поля Elasticsearch передается, используя опцию —fields. Таким образом, мы можем минимизировать объем данных, которые мы на самом деле дублируем:

mongo-connector -m localhost:27017 -t localhost:9200 --fields title,text -d mongo_connector/doc_managers/elastic_doc_manager.py

Подобно тому, как вы видите сообщения Reddit, напечатанные в STDOUT reddit2mongo, вы должны увидеть выходные данные, полученные из Mongo Connector, регистрирующие факт, что каждый документ был перенаправлен в ES примерно в одно и то же время! Какая красивая сцена!

В поисках, упруго

Теперь мы готовы использовать Elasticsearch для выполнения нечетких текстовых запросов к нашему набору данных по мере его поступления из MongoDB. Поскольку мы транслируем прямо с веб-сайта Reddit, я не могу точно сказать, какие результаты вы найдете в своем наборе данных, но, поскольку этот конкретный уголок Интернета, кажется, любит кошек почти так же, как мы любим поисковые системы, вероятно, это безопасно Сказать, что запрос котенка приведет вас куда-то:

curl -XPOST ‘http://localhost:9200/reddit.posts/_search’ -d’{
  "query": {
    "match": {
      "title": {
        "query": "kitten",
        "fuzziness": 2,
        "prefix_length": 1
      }
    }
  }
}’

Поскольку мы выполняем нечеткий поиск, мы можем даже выполнить поиск для слов без слов . Поскольку большинство людей не слишком осторожны с написанием, вы можете представить, насколько мощна эта функция при выполнении текстового поиска, основанного непосредственно на вводе пользователя:

curl -XPOST ‘http://localhost:9200/reddit.posts/_search’ -d’{
  "query": {
    "match": {
      "title": {
        "query": "kiten",
        "fuzziness": 2,
        "prefix_length": 1
      }
    }
  }
}’

fuzzinessПараметр определяет максимальное «расстояние редактирования» текст запроса может быть для того , чтобы соответствовать поле. prefix_lengthПараметр говорит , что результаты должны соответствовать первой букве запроса. Эта статья предлагает отличное объяснение того, как это работает. Этот поиск дал мне те же результаты, что и его правильно написанная версия.

Больше, чем просто вставки

Хотя наша демонстрация просто использовала преимущества непрерывной потоковой передачи документов из MongoDB в Elasticsearch, Mongo Connector — это больше, чем просто инструмент импорта / экспорта. Когда вы обновляете или удаляете документы в MongoDB, эти операции реплицируются и на другие ваши системы, поддерживая синхронизацию всех систем с текущим первичным набором реплик. Если основной отказоустойчивый и происходит откат, Mongo Connector может обнаружить их и сделать все правильно, чтобы сохранить согласованность независимо.

резюмировать

Самое замечательное в этом то, что мы выполняем операции в MongoDB и Elasticsearch одновременно. Без такого инструмента, как Mongo Connector, нам пришлось бы использовать такой инструмент, как mongoexportпериодическая выгрузка данных из MongoDB в JSON, а затем загрузить эти данные в пустой индекс Elasticsearch, чтобы у нас не было ранее удаленных документов. Это, вероятно, было бы огромной проблемой, и мы потеряли бы возможности нашего поискового движка, работающего на ES, почти в реальном времени.

Хотя Mongo Connector значительно улучшился с момента его первого выпуска, это все еще экспериментальный проект, и у него есть способы до официальной поддержки MongoDB, Inc. Но я полон решимости отвечать на вопросы, а также просматривать запросы функций и отчеты об ошибках, сообщаемые Mongo. Страница с сообщениями о соединителях на Github. Также обязательно ознакомьтесь с полной документацией на вики-странице Github.

Ресурсы