17 августа 2023

Поисковый сервис на базе Manticore Search

Поисковый сервис на базе Manticore Search

Manticore Search — это база данных с открытым исходным кодом, предоставляющая возможности полнотекстового поиска.

Вопрос организации поискового сервиса Manticore Search обширен, рассмотрим общие принципы и утилитарные функции, подходящие для основных задач.

Что такое полнотекстовой поиск на базе Manticore Search?

Полнотекстовый поиск — поиск больших объёмов информации, в результате которого данные приводятся к одному нормализованному виду на основе морфологии (по однокоренным словам) и сохраняются в некую структуру.

Можно сохранить количество вхождений конкретного слова в тексте, его позицию в тексте и вес слова относительно всего текста. На основе полученных данных формируется поисковый индекс.

Преимущества Manticore Search

С помощью Manticore Search проще достичь релевантности поиска — можно искать слова, используя морфологические данные, пользовательские словоформы или лексическое значение.

Сбор данных из различных источников и унификация информации для поиска и выдачи клиенту — важное преимущество сервиса Manticore Search. Часто данные, которые мы пытаемся «вытащить», могут находиться в разных базах. Кроме того, источники данных могут быть разные — это могут быть MySQL, PostgreSQL, XML-файлы и так далее. Manticore позволяет собирать и агрегировать эти данные.

Manticore Search упрощает поиск — мы ищем данные по ранее сформированному индексу и обращаемся за поиском информации к одной заранее проиндексированной таблице.

В Manticore реализован распределенный индекс — он позволяет масштабироваться из коробки, формировать индекс на разных машинах и собирать их одновременно. Распределённый поисковый индекс подходит для работы с большим объемом данных и обеспечения отказоустойчивости.

Какие проблемы решает Manticore

Когда мы работаем с понятными сущностями — пользователь, товар, заказ — мы пользуемся привычными инструментами и известными алгоритмами. У таких объектов есть уникальные числовые идентификаторы, их легко сохранять, менять или удалять.

Как быть в случае, когда требуется получить срез данных по определенным критериям? Набор критериев может быть разным — например, нужно агрегировать информацию по разным фильтрам, в том числе кастомным.

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

Manticore умеет решать эту задачу — сервис позволяет определить, какие данные будут использоваться для сортировки или фильтрации.

Ещё одна частая проблема — конкурентный доступ к данным. Когда вы обращаетесь к таблице за поиском сущностей, может случиться так, что в этот момент в эту таблицу кто-то добавляет новые сущности, таблица может заблокироваться и запрос зависнет.

Чтобы не допустить этого, Manticore сохраняет копию источника данных, чтобы вы могли в любой момент времени получить к нему доступ.

Как работает Manticore Search?

Чтобы сохранить все слова и провести по ним поиск, Manticore предварительно анализирует:

  • списки стоп-слов. На этом этапе отсеиваются слова, которые не влияют на поиск — предлоги, местоимения и т.д.;
  • списки замены словоформ. Можно загрузить собственный словарь с актуальными и корректными для бизнес-задачи значениями слов, чтобы искать их по этому значению;
  • морфологические и стемминг-словари на разных языках. Поиск можно производить по корню слова (морфология) или по грамматике (стемминг).

После этого все слова сохраняются и откладываются в Manticore Search. Теперь по ним можно производить полнотекстовой поиск.

В Manticore реализовано два подхода:

  • Сбор данных из сторонних источников — Manticore забирает данные из баз данных и строит индекс по существующим данным. Такой формат можно назвать простым индексом.
  • Индекс реального времени — индекс данных, получаемых из Manticore напрямую в реальном времени. Для такого индекса база Manticore используется именно в качестве основной — если вам нужно обеспечить максимальную оперативность актуализации данных, такой способ будет оптимальным.

Требования к входящим данным

У документа, который нужно индексировать, должны быть обязательные поля:

  • ID — уникальный числовой идентификатор документа (int64). При хранении даже миллиона строк на неограниченном количестве серверов, ID документа будет уникальным независимо от источника данных;
  • UpdatedAt — дата и время обновления документа. По этому параметру Manticore Search понимает, какие данные нужно обновить и как их сгруппировать;
  • DeletedAt - дата и время удаления документа. Manticore не производит поиск по удалённым документам, но запоминает и фиксирует момент их удаления.

В Manticore очень много тонких настроек, поэтому дополнительные поля в индексируемых документах будут отличаться в зависимости от ваших задач.

Таблица 1 - Типы данных для простых индексов

Обозначение Описание
sql_attr_bigint 64 разрядные числа со знаком
sql_attr_string строки
sql_attr_uint 32 разрядные числа без знака
sql_attr_float дробные числа одинарной точности (иногда из-за отсутствия одинарной точности могут возникнуть проблемы, например, при получении цен с копейками)
sql_attr_timestamp дата и время в числовом виде
sql_attr_bool булево значение (в базе хранится как число 0 и 1), флаги
sql_attr_json json-данные

Таблица 2 - Типы данных для индексов реального времени

Обозначение Описание
rt_attr_bigint 64 разрядные числа со знаком
rt_attr_string строки
rt_attr_uint 32 разрядные числа без знака
rt_attr_float дробные числа числа одинарной точности
rt_attr_timestamp дата и время в числом виде
rt_attr_bool булево значение, флаги
rt_attr_json json данные

Как развернуть Manticore?

Существует два варианта установки Manticore — устанавливать на хост-машину или поднимать в docker-контейнере. Наша команда ТЕХНОНИКОЛЬ использует второй вариант — он более гибкий, масштабируемый и управляемый.

Для удобства работы наш ведущий разработчик Константин Шамиев написал приложение на golang, доступное в этом репозитории https://gitlab.tn.ru/golang/template/manticore. Задача этого приложения — взять на себя всю обслуживающую функцию, чтобы оно работало по системе чёрного ящика.

1.png

Алгоритм установки такой:

  • используем docker-контейнер и собираем сервис-приложение;
  • в рабочем образе настраиваем Manticore со всеми необходимыми компонентами (компоненты могут варьироваться в зависимости от задачи);
  • после сборки получаем docker-образ и подключаем его.

Этот docker-образ предусматривает установку на хост-машину трёх основных хранилищ.

В первом хранилище складываются логи Manticore:

  • лог работы сервис-приложения;
  • лог поискового движка Manticore, в котором он пишет процесс индексации;
  • лог запросов к сервису Manticore для получения информации.

Все логи вынесены на хост — так с ними проще работать.

Второе хранилище содержит индекс-дату, в которую будут попадать все проиндексированные данные.

Третье хранилище — конфигурационный файл Manticore. Он содержит данные о том, какие индексы нужно собирать.

Важно понимать, что сервис-приложение и Manticore будучи в одном docker-контейнере не мешают другу другу. Cервис-приложение работает как сторонний контроллер — оно индексирует данные, следит за работоспособностью Manticore, но при этом никак не влияет на запрос, который приходит от пользователя. Сам запрос попадает напрямую в Manticore.

Основные источники, из которых Manticore может брать данные «из коробки»:

  • DB Postgress;
  • DB MySQL;
  • DB ODBC;
  • CSV, XML.

Manticore работает по трем протоколам.

  • port 9306 используется по умолчанию для MySQL-клиента для формирования запросов с помощью синтаксиса, поддерживаемого спецификацией MySQL;
  • port 9308 — это протокол для HTTP/HTTPS. В Manticore можно напрямую с фронта обращаться к сервису поиска;
  • port 9312 — бинарный протокол для взаимодействия между нодами и работы с распределённым индексом.

Масштабировать поиск можно при помощи использования разных нод — если все контейнеры связаны, Manticore может взять оттуда данные.

https://lh4.googleusercontent.com/awIYGi2K0COtp92-Vdq5qCe6wZqeU_ETTREueOvJZdkZ6yc6J-Z95jYVP6U_XRqPyXUtZKzji9nX_e7nz7d3wLuX3b9WE508zEfHxH_5v72-Xf2VssmU5fr9WoGVKK71Ffkf6TGh406BWaKyi1G521cjxBEpjFeEdNvZdZ5tqMd6DDsVmcG7pzqmem-12A

Как устроен код для работы с Manticore?

Проще всего разобрать устройство кода на примере кейса, который работает для 90% задач.

Настроим несколько поисковых индексов:

1) основной индекс (main). Его задача — индексировать большой объём данных на текущий момент времени. Ротация производится редко, раз в месяц или в неделю;

2) вспомогательный индекс (delta). Он должен индексировать данные, изменённые в моменте времени. Ротация индекса каждые 5 минут;

3) объединённый индекс (distributed). Агрегирует main и delta, присваивая им собственный индекс.

Структура кода для задачи Manticore (на примере кейса с индексами main и delta) состоит из следующих блоков:

  • данные для подключения;
  • директивы для индексации;
  • начальные настройки;
  • настройки порционности сбора данных;
  • поисковый запрос;
  • пост-запросы для служебной отработки;
  • блок настроек;
  • код индекса.

Что важно знать про блок настроек?

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

Manticore позволяет изменить эту настройку — вы можете добавить полнотекстовым данным функцию атрибутов или использовать полнотекстовые данные только для атрибуции, заменив их тип.

Кроме того, в блоке настроек можно отключить сохранение в Manticore исходных данных для оптимизации работы.

Как управлять порционностью сбора данных?

Чтобы Manticore справилась с объёмом данных для анализа, их нужно брать порционно. Для этого есть предназначены настройки:

  • sql_range_step — количество строк данных, которое Manticore должна собрать в единицу времени;
  • sql_ranged_throttle — время промежутка между сборами порций.

Индекс содержит следующие поля:

  • тип индекса;
  • место хранения в docker-контейнере;
  • источник индексации;
  • настройка поискового индекса.

Атрибуты настройки могут содержать стоп-листы (с указанием пути до файла или с помощью обращения к предустановленным стоп-листам), пользовательские словоформы, настройки морфологии языка.

Для сопутствующих индексов (таких как delta) не нужно дублировать код настройки — он наследует у родительского индекса (в нашем случае main) все общие параметры, поэтому для индекса delta достаточно только прописать его уникальные настройки.

Что ещё можно изучить про Manticore Search?

На сайте https://play.manticoresearch.com/ есть интерактивные курсы на тему различных решений. Но они подходят в основном для того, чтобы понять принципы работы Manticore.

Большая часть ответов, прикладные детали и параметры настроек содержатся в документации: https://manual.manticoresearch.com/Introduction.

3