В этом посте мы обсудим, как быстро начать использовать 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 connector, например) или JOIN между индексами, которые пока не поддерживаются.
Сначала давайте подключимся к Manticore Search и посмотрим на доступные индексы:
$ mysql -P9306 -h0
mysql> SHOW TABLES;
+-------+-------------+
| Index | Type |
+-------+-------------+
| dist1 | distributed |
| testrt| rt |
+-------+-------------+
2 rows in set (0.00 sec)
Теперь давайте посмотрим на наш RT индекс:
mysql> DESCRIBE testrt;
+---------+--------+
| Field | Type |
+---------+--------+
| id | bigint |
| title | field |
| content | field |
| gid | uint |
+---------+--------+
4 rows in set (0.00 sec)
Поскольку RT индексы изначально пусты, давайте сначала добавим в них данные.
mysql> INSERT INTO testrt VALUES(1,'List of HP business laptops','Elitebook Probook',10);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testrt VALUES(2,'List of Dell business laptops','Latitude Precision Vostro',10);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testrt VALUES(3,'List of Dell gaming laptops','Inspirion Alienware',20);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO testrt VALUES(4,'Lenovo laptops list','Yoga IdeaPad',30);
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO testrt VALUES(5,'List of ASUS ultrabooks and laptops','Zenbook Vivobook',30);
Query OK, 1 row affected (0.01 sec)
Теперь у нас есть некоторые данные, мы можем выполнять запросы.
Полнотекстовые поиски выполняются с помощью специального предложения MATCH, которое является основным рабочим инструментом.
mysql> SELECT * FROM testrt WHERE MATCH('list of laptops');
+------+------+
| id | gid |
+------+------+
| 1 | 10 |
| 2 | 10 |
| 3 | 20 |
| 5 | 30 |
+------+------+
4 rows in set (0.00 sec)
Как вы видите в наборе результатов, мы можем получить только идентификатор документа и атрибуты. Значения полей полнотекстового поиска не возвращаются, так как текст только индексируется, но не сохраняется, и невозможно восстановить оригинальный текст.
Теперь давайте добавим немного фильтрации и больше сортировки:
mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCG('list of laptops') AND gid>10 ORDER BY WEIGHT() DESC,gid DESC;
+------+------+----------+
| id | gid | weight() |
+------+------+----------+
| 5 | 30 | 2334 |
| 3 | 20 | 2334 |
+------+------+----------+
2 rows in set (0.00 sec)
Функция WEIGHT() возвращает рассчитанный балл соответствия. Если сортировка не указана, результат сортируется по убыванию по баллу, предоставленному WEIGHT(). В этом примере мы сначала сортируем по весу, а затем по целочисленному атрибуту.
Поиск выше выполняет простое соответствие, где все слова должны присутствовать. Но мы можем сделать больше (и это всего лишь простой пример):
mysql> SELECT *,WEIGHT() FROM testrt WHERE MATCH('"list of business laptops"/3');
+------+------+----------+
| id | gid | weight() |
+------+------+----------+
| 1 | 10 | 2397 |
| 2 | 10 | 2397 |
| 3 | 20 | 2375 |
| 5 | 30 | 2375 |
+------+------+----------+
4 rows in set (0.00 sec)
mysql> SHOW META;
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| total | 4 |
| total_found | 4 |
| time | 0.000 |
| keyword[0] | list |
| docs[0] | 5 |
| hits[0] | 5 |
| keyword[1] | of |
| docs[1] | 4 |
| hits[1] | 4 |
| keyword[2] | business |
| docs[2] | 2 |
| hits[2] | 2 |
| keyword[3] | laptops |
| docs[3] | 5 |
| hits[3] | 5 |
+---------------+----------+
15 rows in set (0.00 sec)
Здесь мы ищем 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 # optional, default is 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', 'this is my test document number one. also checking search within phrases.' ),
( 2, 1, NOW(), 'test two', 'this is my test document number two' ),
( 3, 2, NOW(), 'another doc', 'this is another group' ),
( 4, 2, NOW(), 'doc number four', 'this is to test groups' );
Если вы хотите использовать другую таблицу, имейте в виду, что первый столбец в наборе результатов должен быть беззнаковым уникальным целым числом - в большинстве случаев это ваш первичный ключ 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 rows in set (0.00 sec)
mysql> SELECT * FROM test1;
+------+----------+------------+
| id | group_id | date_added |
+------+----------+------------+
| 1 | 1 | 1507904567 |
| 2 | 1 | 1507904567 |
| 3 | 2 | 1507904567 |
| 4 | 2 | 1507904567 |
+------+----------+------------+
4 rows in set (0.00 sec)
Быстрый тест поиска, который должен соответствовать 2 терминам, но не соответствовать другому:
mysql> SELECT * FROM test1 WHERE MATCH('test document -one');
+------+----------+------------+-------+
| id | group_id | date_added | tag |
+------+----------+------------+-------+
| 2 | 1 | 1519040667 | 2,4,6 |
+------+----------+------------+-------+
1 row in set (0.00 sec)