Originally published at
Развитие личности, лайфхак, личный опыт, проекты и околоайтишные размышления. Персональный блог Станислава Малкина. You can comment here or
there.
Итак, сфинкс.
Постараюсь немного рассказать о нем с наглядными примерами и настройкой.
Sphinx (SQL Phrase Index) - полнотекстовый поисковой движок, опубликованный под лицензией GPLv2, что дает возможность его бесплатного использования в своих проектах.
Сразу же возникает вопрос - «чем же Sphinx отличается от других поисковых движков и почему именно его стоит использовать?»
Кроме всех достоинств Sphinx (быстрая индексация, поддержка MySQL и PostgreSQL, морфология и т.д.) я бы отметил еще такие особенности, как распределенный поиск (возможность размазывать поисковой движок на несколько машин) и довольно широкое использование движка в hiload проектах (к примеру на Habrahabr и т.д.).
Я много слышал о Sphinx, но до этого не было повода и надобности в его использовании. Однако времена меняются.
Я уже рассказывал про создание
видеохостинга своими руками . В один прекрасный день встал вопрос поиска по базе видеофайлов. До этого использовался гуглопоиск, но его качество оставляло желать лучшего в плане поиска по видео, несмотря на то, что Sitemap для video.google.com был скормлен.
Поэтому я задался вопросом создания поиска по видео. Естественно, изобретать велосипед мне не хотелось (писать поиск с нуля), поэтому начал смотреть на готовые решения и вспомнил про Sphinx. Почему бы и нет? Познакомиться с новой для себя технологией, заодно решить задачу.
Сказано - сделано. Начал изучать документацию. Сначала вообще мало что было понятно.
Установка
Начал отсюда -
http://www.sphinxsearch.com/docs/manual-0.9.9.html#quick-tour , поставил себе sphinx (у меня там Fedora):
yum list | grep sphinx
yum install sphinx.x86_64
Конфиг
Дальше отредактировал конфиг, предварительно скопировав его с директории установки и переименовав в sphinx.conf (тут довольно много времени пришлось убить на ознакомление с документацией и правильной настройки конфига. В итоге получилось такое:
# Minimal Sphinx configuration sample (clean, simple, functional)
#
source video
{
type = mysql
sql_host = localhost
sql_user = myuser
sql_pass = mypass
sql_db = mydb
sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 sql_query_pre = SET SESSION query_cache_type=OFF
sql_query = \
SELECT `desc`, `longdesc`, \
(SELECT count(`id`) FROM `comments` WHERE `item_id` = v.`video_id`) as comments, \
UNIX_TIMESTAMP(`date`) AS date_added, `views` as views \
FROM video v WHERE `decoded` = ’1’ AND `deleted` = 0
sql_attr_uint = comments
sql_attr_uint = views
sql_attr_timestamp = date_added
}
index video
{
source = video
path = /var/lib/sphinx/video
docinfo = extern
charset_type = utf-8
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
enable_star = 1 min_prefix_len = 5 html_strip = 1 prefix_fields = desc, longdesc
morphology = none
}
indexer
{
mem_limit = 32M
}
searchd
{
port = 3312 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
max_matches = 1000 seamless_rotate> = 1 preopen_indexes = 0 unlink_old = 1 }
В принципе все довольно стандартно, главное было подобрать параметры «под себя». Про все параметры можно прочесть в документации, поэтому по ним пробегусь довольно коротко:
sql_query_pre = SET NAMES utf8 sql_query_pre = SET SESSION query_cache_type=OFF
Эта часть означает, что мы делаем два предварительных запроса к базе до выполнения основного запроса на выборку данных, в которых выставляет кодировку utf8 для считываемых данных и отключаем кеширование запросов.
charset_type = utf-8
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
Для правильного поиска по индексу выставляем индексатору правильную кодировку данных и список допустимых символов в этой кодировке (куда, кстати, попадают и русские буквы)
enable_star = 1 min_prefix_len = 5 html_strip = 1 prefix_fields = desc, longdesc
Включаем префиксирование до 5 символов для полей desc, longdesc и вырезаем все хтмл-символы. Теперь, запрашивая что слово «шевч*» (со звездой в конце - именно это означает enable_star) - мы сможем найти слова, начинающиеся с «шевч» и имеющие от 1 до 5 символов после, например «шевченко» или «шевчук» и т.д.
Проверка работоспособности и сron
Т.к. конфиг создан, самое время проверить, что он правильно работает и в нем нет ошибок. Для этого в консоли набираем вот такое:
indexer video -rotate
Результат будет подобен этому, если с конфигом все хорошо:
Sphinx 0.9.8.1-release (r1533)
Copyright © 2001-2008, Andrew Aksyonoff
using config file ’/etc/sphinx/sphinx.conf’…
indexing index ’video’…
collected 4549 docs, 0.3 MB
sorted 0.1 Mhits, 100.0% done
total 4549 docs, 308441 bytes
total 0.401 sec, 768480.12 bytes/sec, 11333.82 docs/sec
rotating indices: succesfully sent SIGHUP to searchd (pid=31147).
Параметр «-rotate» задан всего-лишь потому, что демон searchd у меня уже запущен и без него данные невозможно будет обновить, т.к. файлы залочены. Если у вас демон еще не запущен после установки, параметр просто опустите.
Если ошибок нету и индекс создался - самое время запустить демон, если еще не запущен (/etc/init.d/searchd start) и занести индексацию данных в крон (я поставил обновление индекса раз в 30 минут):
30 * * * * /usr/bin/indexer -rotate video > /dev/null 2>&1
Остается проверить, что поиск работает правильно. Для этого в консоли опять же следует набрать что-то типа такого:
search lol
и получим такой результат:
Sphinx 0.9.8.1-release (r1533)
Copyright © 2001-2008, Andrew Aksyonoff
using config file ’/etc/sphinx/sphinx.conf’…
index ’video’: query ’lol ’: returned 2 matches of 2 total in 0.000 sec
displaying matches:
1. document=1501, weight=1, comments=0, rating=0, date_added=Thu Oct 22 12:57:55 2009, views=406 2. document=2502, weight=1, comments=2, rating=4, date_added=Mon Nov 30 11:18:40 2009, views=415 words:
1. ’lol’: 2 documents, 2 hits
Отлично - найдено два совпадения, значит поиск работает правильно.
Sphinx и PHP
Т.к. поиск работает - остается теперь запрашивать данные у демона из PHP и выводить результаты. Для этого есть два пути - использовать PHP API просто делая инклуд его в код или установить расширение из pecl (php-pecl-sphinx.x86_64).
Я решил не тягать за собой код и поставить расширение - «взула и забула». Как обычно - yum install php-pecl-sphinx.x86_64 и через пару секунд расширение уже установлено и работает.
Дальше все просто - читаем мануал отсюда -
http://php.net/sphinx и пишем в нужном месте обращение к демону searchd:
$s = new SphinxClient;
$s->setMaxQueryTime(3);
$s->setSortMode(SPH_SORT_RELEVANCE);
$s->setMatchMode(SPH_MATCH_ANY);
$result = $s->query($query);
Код довольно тривиален и призван лишь показать пример элементарного использования. Естественно, сюда можно добавить лимитирование (setLimits) и другие вкусные вещи на ваше усмотрение - в этом вам поможет документация с указанного выше раздела.
Замечание: запрос к sphinx возвращает всего-лишь набор айди (как правило - primary key) записей в таблице, которые удовлетворяют заданному поиску. Вам нужно будет доставать данные из базы самостоятельно после получения результата от демона (в этом вам поможет запрос SELECT * FROM documents WHERE id IN (3,5,7) ORDER BY FIELD(id,3,5,7), модифицированный под ваши надобности).
Заключение
Данный обзор не претендует на полноту и носит лишь ознакомительный характер для демонстрации базовой установки и настройки sphinx для ваших надобностей.
Автор готов оказать помощь (в пределах своих знаний) в комментариях для тех, кто столкнулся с какими-либо проблемами при установке и настройке Sphinx.
Личное мнение автора - движок очень легкий, приятный в использовании и не требует долгих танцев с бубном над собой для приведения «в чувство».
--------------------------------
P. S. Совсем недавно открылся сайт
школы фриланса, к созданию сайта которой я приложил свою руку. Проект работает на базе маленькой CMS системки, которую я создал с помощью Zend Framework.
P. P. S.
Написал анонс нового проекта школы фриланса - «стенка на стенку» на
freelancehack.ru. Знаю, меня читают фрилансеры, возможно заинтересует.