Поисковый движок SPHINX.
Установка движка в CentOS7
1. Скачиваем с сайта пакет RPM
http://sphinxsearch.com/downloads/release/
Я выбрал пакет RHEL/CentOS 7.x x86_64 RPM 2.2.11-release (6.2M)
2. Копируем пакет в папку /usr/src
3. В консоли переходим в папку с пакетом
# cd /usr/src/
4. Проводим установку sphinx
# yum install -y sphinx-2.2.11-1.rhel7.x86_64.rpm
Вместе с необходимым пакетом установятся так же postgresql-libs и unixODBC
5. Конфигурационный файл службы - /etc/sphinx/sphinx.conf
Зарезервируем на всякий случай конфигурационный файл
# cp /etc/sphinx/sphinx.conf /etc/sphinx/sphinx.conf.default
Настройка сервиса sphinx для работы с базой MySQL и запуск сервиса
1. Для работы поиска с помощью sphinx сделаем тестовую базу данных MySQL, наполним ее тестовыми данными, проведем создание индекса:
Подключаемся к базе MySQL (MariaDB)
# mysql -u root –p
Создаем базу test
> CREATE DATABASE test;
Заливаем тестовые данные, которые присутствуют в /usr/share/doc/sphinx-2.2.11/example.sql
> SOURCE /usr/share/doc/sphinx-2.2.11/example.sql;
Выходим из базы
> quit;
Тестовые данные представляют из себя таблицу с записями, содержащими текст. Упрощенно это записи:
( 1, 'test one', 'this is my test document number one. also checking search within phrases.' ),
( 2, 'test two', 'this is my test document number two' ),
( 3, 'another doc', 'this is another group' ),
( 4, 'doc number four', 'this is to test groups' )
2. Редактируем имеющийся конфигурационный файл. Он по умолчанию создан для работы с базой MySQL. Файл содержит несколько секции
source – раздел описывает источник данных
index – раздел описывает местоположение индекса и с каким источником будет работать индекс. Их может быть несколько. Один для испытаний я закомментировал
indexer – раздел описывает параметры работы с индексами
searchd – здесь описание демона sphinx
# nano /etc/sphinx/sphinx.conf
Содержимое тестового конфигурационного файла:
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#
source src1
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass = **********
sql_db = test
sql_port = 3306
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/sphinx/test1
}
indexer
{
mem_limit = 128M
}
searchd
{
listen = 9312
listen = 9306:mysql41
log = /var/log/sphinx/searchd.log
query_log = /var/log/sphinx/query.log
read_timeout = 5
max_children = 30
pid_file = /var/run/sphinx/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
workers = threads # for RT to work
binlog_path = /var/lib/sphinx/
}
3. Создадим индекс используя конфигурационный файл
# indexer –-all
Вывод будет следующий:
Sphinx 2.2.11-id64-release (95ae9a6)
Copyright (c) 2001-2016, Andrew Aksyonoff
Copyright (c) 2008-2016, Sphinx Technologies Inc (http://sphinxsearch.com)
using config file '/etc/sphinx/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.041 sec, 4682 bytes/sec, 97.04 docs/sec
total 4 reads, 0.000 sec, 0.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
4. Запуск демона sphinx
# systemctl start searchd
Добавление в автозагрузку
# systemctl enable searchd
Проверка статуса:
# systemctl status searchd
5. Подключиться к серверу sphinx используя клиент MySQL
# mysql -h0 -P9306
Получим приглашение
MySQL [(none)]>
Проверка поиска по тестовой базе. Найдем фразу 'test document'
MySQL [(none)]> SELECT * FROM test1 WHERE MATCH('test document');
+------+----------+------------+
| id | group_id | date_added |
+------+----------+------------+
| 1 | 1 | 1507959119 |
| 2 | 1 | 1507959119 |
+------+----------+------------+
2 rows in set (0.00 sec)
Проверка поиска по ключевым словам в тестовой базе
MySQL [(none)]> CALL KEYWORDS ('test one three', 'test1', 1);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1 | test | test | 3 | 5 |
| 2 | one | one | 1 | 2 |
| 3 | three | three | 0 | 0 |
+------+-----------+------------+------+------+
3 rows in set (0.00 sec)
Видно, что индекс построился правильно. Поиск работает. Обращаясь к сервису, мы можем получить ID записи в базе.
Настройка Sphinx для работы с источником данных xml
1. Для того, чтобы сервер успешно создал индекс, необходимо подготовить правильную структуру данных. Пример структуры данных разместим в /mnt/base.xml
<?xml version="1.0" encoding="utf-8"?>
<sphinx:docset xmlns:sphinx="http://sphinxsearch.com/">
<sphinx:schema>
<sphinx:field name="name" attr="string" />
</sphinx:schema>
<sphinx:document id="800">
<name>
ip address
</name>
</sphinx:document>
<sphinx:document id="801">
<name>MAC address</name>
</sphinx:document>
<sphinx:document id="802">
<name>get post html</name>
</sphinx:document>
<sphinx:document id="803">
<name>Мой документ</name>
</sphinx:document>
</sphinx:docset>
2. Настройка конфигурации для парсинга xml документа будет такой:
# nano /etc/sphinx/sphinx.conf
Раздел source:
source basexml
{
type = xmlpipe2
xmlpipe_command = /usr/bin/cat /mnt/base.xml
}
Главное здесь – это команда, которая будет читать данные и выводить в стандартный вывод linux. В нашем случае – это /usr/bin/cat /mnt/base.xml
Раздел index
index knowledgebase
{
source = knowledgebase
path = /var/lib/sphinx/knowledgebase
# Минимальная длина слова
min_word_len = 2
min_prefix_len = 3
html_strip = 1
# Позволяет использовать звездочки в запросах, к примеру
# по запросу *пр* будут найдены проспект, привет и пр.
enable_star = 1
# Автоматически расширяет поисковый запрос до трех запросов
# running -> ( running | *running* | =running )
expand_keywords = 1
index_exact_words = 1
morphology = stem_enru
}
3. Перезапуск процесса построения индексов выполняет так
# indexer --all --rotate
Sphinx 2.2.11-id64-release (95ae9a6)
Copyright (c) 2001-2016, Andrew Aksyonoff
Copyright (c) 2008-2016, Sphinx Technologies Inc (http://sphinxsearch.com)
using config file '/etc/sphinx/sphinx.conf'...
indexing index 'basexml'...
collected 3 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 3 docs, 38 bytes
total 0.005 sec, 7165 bytes/sec, 565.71 docs/sec
indexing index 'test1'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 193 bytes
total 0.003 sec, 57134 bytes/sec, 1184.13 docs/sec
total 13 reads, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg
total 24 writes, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg
rotating indices: successfully sent SIGHUP to searchd (pid=2372).
4. Поиск по индексу basexml слова ‘post’ выполняется так же:
# mysql -h0 -P9306
MySQL [(none)]> SELECT * FROM basexml WHERE MATCH('post');
+------+---------------+
| id | name |
+------+---------------+
| 802 | get post html |
+------+---------------+
1 row in set (0.00 sec)
5. Для того что бы сделать периодическую ротацию индексов, в cron помещаем задание, которое будет выполняться к примеру дву раза в день:
/usr/bin/indexer --rotate --config /etc/sphinx/sphinx.conf --all > /dev/null
Использование PHP для работы с сервером Sphinx.
Для работы в PHP с сервером sphinx можно использовать два подхода:
1) Sphinx API
2) SphinxQL
Будем использовать второй способ, как наиболее простой. Этот способ позволяет обращаться к серверу через клиент MySQL и работать с SQL подобным языком запросов. В PHP необходимо использовать PDO для подключения к серверу.
Пример кода:
$db = new PDO('mysql:host=127.0.0.1;port=9306;charset=utf8', '', '');
$q = "SELECT id FROM knowledgebase WHERE MATCH('".$what_sphinx."');";
$stmt = $db->query($q);
if($stmt->rowCount() > 0) {
foreach ($stmt->fetchAll() as $row) {
$arr_sphinx_rez[] = $row['id'];
}
}
В переменной $what_sphinx можно писать просто слово, так и использовать выражения OR (|) или AND (&)