Добрый день, хаброжители!
Представляю вашему вниманию расширение для PostgreSQL, позволяющее отправлять поисковые запросы на Sphinx из PostgreSQL и получать результаты этих запросов.
Подробности реализации и ссылка на репозиторий под катом.
Предисловие
В одном крупном web проекте потребовалось использование полнотекстового движка Sphinx. И все бы хорошо, если бы не потребовалось результаты запросов от Sphinx дополнительно сортировать по хитро заданным правилам внутри базы.
И тут встал очевидный вопрос: как? Тут напрашиваются как минимум два варианта:
- Делать полнотекстовый запрос в Sphinx, результаты сортировать в приложении;
- Воспользоваться мощью SQL в PostgreSQL для получения данных поисковых запросов из Sphinx в табличной форме с возможностью дополнительной обработки в базе.
Взвесив все плюсы и минусы указанных вариантов, было реализовано расширение sphinxlink. Идея реализации была честно подсмотрена с расширения dblink.
Функции расширения и детали реализации
Как и в dblink, управление всем осуществляется с помощью SQL функций, написанных на C.
Клиентский протокол взаимодействия с Sphinx соответствует протоколу взаимодействия mysql, а это значит, что мы можем использовать самую обыкновенную библиотеку mysql-client для подключения к Sphinx.
Для подключения к серверу Sphinx используется функция sphinx_connect():
SELECT * FROM sphinx_connect('myconn');
sphinx_connect
----------------
OK
(1 строка)
Подключения создаются в статической области памяти бэкенда в виде структуры HTAB, поэтому при закрытии закрытии сессии все созданные соединения к Sphinx будут закрыты.
Для просмотра списка открытых соединений с Sphinx и параметров подключения используется функция sphinx_connections():
SELECT * FROM sphinx_connections();
conname | host | port
---------+-----------+------
myconn | 127.0.0.1 | 9306
(1 строка)
А теперь, как отправлять поисковые запросы и получать результаты.
Получение результатов поискового запроса в табличной форме реализовано в функции sphinx_query(). Важно при этом указать название столбцов и их типов данных для корректного формирования результата.
Например, создадим индекс в Sphinx со следующей структурой:
DESC myindex;
+---------+--------+
| Field | Type |
+---------+--------+
| id | bigint |
| content | field |
| title | string |
+---------+--------+
В поле content будут лежать тексты документов (например, рассказы А.П. Чехова), в поле title — название рассказа, поле id — идентификатор текста (служебное поле в Sphinx).
SELECT * FROM sphinx_query('myconn', 'SELECT weight(), * FROM myindex WHERE MATCH(''красота'')') AS (weight integer, docid integer, title text);
weight | docid | title
--------+-------+-------
1680 | 3 | Дома
(1 строка)
Для запроса метаинформации по последнему запросу используется функция sphinx_meta():
SELECT * FROM sphinx_meta('myconn');
varname | value
-------------+--------
total | 1
total_found | 1
time | 0.000
keyword[0] | красот
docs[0] | 1
hits[0] | 1
(6 строк)
Данная функция сделана для удобства. Аналогичного эффекта можно добиться, послав запрос SHOW META с помощью функции sphinx_query().
Для закрытия ненужного соединения используется функция sphinx_disconnect():
SELECT * FROM sphinx_disconnect('myconn');
sphinx_disconnect
-------------------
OK
(1 строка)
Планы реализации
У текущей реализации модуля есть ряд недостатков:
- Параметры подключений не сохраняются при завершении сессии PostgreSQL — хотелось бы иметь режим работы, при котором параметры соединения сохранялись в реальную таблицу с целью их получения;
- Все описанное справедливо для запросов на чтение индексов Sphinx, но нет функции управления RT индексами;
- Ваши предложения?
Традиционно для подобных постов, оставляю ссылку на github: sphinxlink.
Комментарии и предложения горячо приветствуются. Спасибо за внимание!
andy128k
github.com/andy128k/pg-sphinx
dimv36 Автор
Ваше расширение видел, но нам требовалось возвращать дополнительные атрибуты из Sphinx, которые по историческим причинам помещались в него. В Вашем расширении данный функционал отсутствует.