Начало работы с Manticore Search в Docker

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

Установка и запуск

Официальные образы Docker размещены по адресу https://hub.docker.com/r/manticoresearch/manticore/ .
Чтобы запустить Manticore Search, вам просто нужно выполнить:

$ docker run --name manticore -p 9306:9306 -d manticoresearch/manticore

Рецепт Docker размещен на github , для тех, кто хочет расширить существующие образы.

Контейнер Manticore Search не имеет постоянного хранилища, и если контейнер остановлен, все изменения теряются. Простым способом обеспечить сохранность является монтирование нескольких папок на локальные машины.

Папки, для которых мы хотим обеспечить сохранность:

  • /etc/sphinxsearch - расположение sphinx.conf
  • /var/lib/manticore/data - используется для файлов индекса
  • /var/lib/manticore/log - используется для файлов журнала

Мы рассматриваем папку manticore/ в нашем домашнем каталоге, где мы создадим папки etc/, data/ и logs/, а также добавим действительный sphinx.conf в ~/manticore/etc/. Мы можем использовать sphinx.conf , который включен в репозиторий рецептов.
К команде запуска мы добавим монтирования:

$ docker run --name manticore -v ~/manticore/etc/:/etc/sphinxsearch/ -v ~/manticore/data/:/var/lib/manticore/data -v ~/manticore/logs/:/var/lib/manticore/log -p 9306:9306 -d manticoresearch/manticore

Контейнер можно остановить простой командой:

$ docker stop manticore

Образ Docker также включает утилиты indexer и indextoo, которые можно запускать с помощью команды exec Docker:

$ docker exec -it manticore indexer --all --rotate

Запуск запросов

Простой способ подключиться и провести некоторые тесты - использовать протокол SphinxQL. Для этого вам нужен клиент командной строки MySQL.

Хотя он реализует протокол MySQL, SphinxQL не является на 100% совместимым с синтаксисом MySQL. Существуют специфические расширения, такие как условие MATCH [самая мощная вещь в Manticore] или WITHIN GROUP BY, и многие функции, доступные в MySQL, не реализованы (или они фиктивные, чтобы обеспечить совместимость с соединителем MySQL, например) или JOIN между индексами, которые еще не поддерживаются.

Сначала давайте подключимся к Manticore Search и посмотрим доступные индексы:

$ mysql -P9306 -h0
mysql> SHOW TABLES;
+-------+-------------+
| Index | Type        |
+-------+-------------+
| dist1 | распределенный |
| testrt| rt          |
+-------+-------------+
2 строки в выборке (0.00 сек)

Теперь давайте взглянем на наш RT индекс:

mysql> DESCRIBE testrt;
+---------+--------+
| Поле   | Тип     |
+---------+--------+
| id      | bigint |
| title   | field  |
| content | field  |
| gid     | uint   |
+---------+--------+
4 строки в выборке (0.00 сек)

Поскольку RT индексы изначально пустые, давайте сначала добавим в них данные.

mysql> INSERT INTO testrt VALUES(1,'Список бизнес-ноутбуков HP','Elitebook Probook',10);
Запрос успешно выполнен, 1 строка затронута (0.00 сек)

mysql> INSERT INTO testrt VALUES(2,'Список бизнес-ноутбуков Dell','Latitude Precision Vostro',10);
Запрос успешно выполнен, 1 строка затронута (0.00 сек)

mysql> INSERT INTO testrt VALUES(3,'Список игровых ноутбуков Dell','Inspirion Alienware',20);
Запрос успешно выполнен, 1 строка затронута (0.00 сек)

mysql> INSERT INTO testrt VALUES(4,'Список ноутбуков Lenovo','Yoga IdeaPad',30);
Запрос успешно выполнен, 1 строка затронута (0.01 сек)

mysql> INSERT INTO testrt VALUES(5,'Список ультрабуков и ноутбуков ASUS','Zenbook Vivobook',30);
Запрос успешно выполнен, 1 строка затронута (0.01 сек)

Теперь у нас есть некоторые данные, мы можем выполнять запросы.

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

mysql> SELECT * FROM testrt WHERE MATCH('список ноутбуков');
+------+------+
| id   | gid  |
+------+------+
| 1    | 10   |
| 2    | 10   |
| 3    | 20   |
| 5    | 30   |
+------+------+
4 строки в выборке (0.00 сек)

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

Теперь давайте добавим немного фильтрации и больше сортировки:

mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCG('список ноутбуков') AND gid>10 ORDER BY WEIGHT() DESC,gid DESC;
+------+------+----------+
| id   | gid  | weight() |
+------+------+----------+
| 5    | 30   | 2334     |
| 3    | 20   | 2334     |
+------+------+----------+
2 строки в выборке (0.00 сек)

Функция WEIGHT() возвращает рассчитанный балл соответствия. Если сортировка не указана, результат сортируется по убыванию по оценке, предоставляемой WEIGHT(). В этом примере мы сначала сортируем по весу, а затем по целочисленному атрибуту.

Вышеуказанный поиск выполняет простое соответствие, где все слова должны присутствовать. Но мы можем сделать больше (и это всего лишь простой пример):

mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCH('"список бизнес-ноутбуков"/3');
+------+------+----------+
| id   | gid  | weight() |
+------+------+----------+
| 1    | 10   | 2397     |
| 2    | 10   | 2397     |
| 3    | 20   | 2375     |
| 5    | 30   | 2375     |
+------+------+----------+
4 строки в выборке (0.00 сек)

mysql> SHOW META;
+---------------+----------+
| Название_переменной | Значение  |
+---------------+----------+
| total         | 4        |
| total_found   | 4        |
| time          | 0.000    |
| keyword[0]    | список    |
| docs[0]       | 5        |
| hits[0]       | 5        |
| keyword[1]    | из       |
| docs[1]       | 4        |
| hits[1]       | 4        |
| keyword[2]    | бизнес   |
| docs[2]       | 2        |
| hits[2]       | 2        |
| keyword[3]    | ноутбуки |
| docs[3]       | 5        |
| hits[3]       | 5        |
+---------------+----------+
15 строк в наборе (0.00 сек)

Здесь мы ищем 4 слова, но мы можем получить совпадение даже если будет найдено только 3 слова (из 4). Поиск будет оценивать выше сначала те документы, которые содержат все слова. Мы также добавили команду SHOW META. SHOW META возвращает информацию о ранее выполненном запросе, а именно количество найденных записей (в total_found), время выполнения (в time) и статистику по ключевым словам поиска.

Использование обычных индексов

В отличие от RT, обычный также требует настройки источника для него. В нашем примере мы используем источник MySQL.

Добавьте в ваш sphinx.conf:

source src1
{
type = mysql

sql_host = 172.17.0.1
sql_user = test
sql_pass =
sql_db = test
sql_port = 3306 # необязательно, по умолчанию 3306

sql_query_pre = SET NAMES utf8

sql_query = \
SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
FROM documents

sql_attr_uint = group_id
sql_attr_timestamp = date_added

}
index test1
{

source = src1
path = /var/lib/manticore/data/test1
min_word_len = 1

}

В этом примере мы предполагаем, что MySQL работает на локальном хосте, но так как Manticore Search работает внутри контейнера Docker, нам нужно использовать ‘172.17.0.1’, статический IP-адрес хоста Docker. Для получения дополнительных сведений, пожалуйста, обратитесь к документации Docker. Вам также нужно настроить учетные данные MySQL соответственно.

Затем мы ищем sql_query, который является запросом, который извлекает данные

sql_query = \
SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
FROM documents

И мы используем этот SQL фрагмент для создания нашей тестовой таблицы в MySQL:

DROP TABLE IF EXISTS test.documents;
CREATE TABLE test.documents
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
group_id INTEGER NOT NULL,
date_added DATETIME NOT NULL,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL
);

INSERT INTO test.documents ( id, group_id, date_added, title, content ) VALUES
( 1, 1, NOW(), 'test one', 'это мой тестовый документ номер один. также проверяется поиск в выражениях.' ),
( 2, 1, NOW(), 'test two', 'это мой тестовый документ номер два' ),
( 3, 2, NOW(), 'another doc', 'это другая группа' ),
( 4, 2, NOW(), 'doc number four', 'это для тестирования групп' );

Если вы хотите использовать другую таблицу, имейте в виду, что первый столбец в наборе результатов должен быть беззнаковым уникальным целым числом - в большинстве случаев это ваш первичный ключ id таблицы.

Если не указано, остальные столбцы индексируются как полнотекстовые поля. Столбцы, которые должны использоваться в качестве атрибутов, необходимо объявить. В нашем примере group_id и date_added являются атрибутами:

sql_attr_uint = group_id
sql_attr_timestamp = date_added

Как только мы настроили это, мы можем запустить процесс индексации:

$ docker exec -it manticore indexer test1 --rotate
using config file '/etc/sphinxsearch/sphinx.conf'...
indexing index 'test1'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 193 bytes
total 0.015 sec, 12335 bytes/sec, 255.65 docs/sec
total 4 reads, 0.000 sec, 8.1 kb/call avg, 0.0 msec/call avg
total 12 writes, 0.000 sec, 0.1 kb/call avg, 0.0 msec/call avg

Индекс создан и готов к использованию:

mysql> SHOW TABLES;
+-------+-------------+
| Index | Type        |
+-------+-------------+
| dist1 | distributed |
| rt    | rt          |
| test1 | local       |
+-------+-------------+
3 строки в наборе (0.00 сек)

mysql> SELECT * FROM test1;
+------+----------+------------+
| id   | group_id | date_added |
+------+----------+------------+
| 1    | 1        | 1507904567 |
| 2    | 1        | 1507904567 |
| 3    | 2        | 1507904567 |
| 4    | 2        | 1507904567 |
+------+----------+------------+
4 строки в наборе (0.00 сек)

Быстрый тест поиска, который должен совпадать с 2 терминами, но не совпадать с другим:

mysql> SELECT * FROM test1 WHERE MATCH('test document -one');
+------+----------+------------+-------+
| id   | group_id | date_added | tag   |
+------+----------+------------+-------+
| 2    | 1        | 1519040667 | 2,4,6 |   
+------+----------+------------+-------+
1 строка в наборе (0.00 сек)

Установить Manticore Search

Установить Manticore Search