Sphinx. Установка, настройка и использование поискового движка
Не так давно, я написал статью "FreeBSD. Установка и настройка Яндекс.Сервер" и пообещал в комментариях рассказать про поисковый движок Sphinx. Это одна из трех запланированных статей про этот замечательный поисковый движок, в следующих статьях расскажу про расширение для PHP и расширение для MySQL.
Операционная система, в которой будем производить установку и настройки - FreeBSD, но так же буду давать советы и для Windows-пользователей.
В качестве примера, будем разрабатывать поиск для моего блога на Wordpress. Для самых не терпеливых, вот демонстрация работы поисковика .
Установка
Установка достаточно простая
# cd /usr/ports/textproc/sphinxsearch # make config
Выбираем:
- "mysql", если вы пользуетесь данной СУБД и хотите работать с данными непосредственно из Sphinx
- "iconv" для поддержки разных кодировок
# make install
Вот и все, установка завершена!
Скачать исходники и Windows-версии можно тут: .
После скачки Windows-версии, достаточно распаковать архив и указать в системной переменной "Path" полный путь до каталога \sphinx\bin.
Настройка
До начала поиска надо проиндексировать вашу информацию, создадим наш конфигурационный файл и укажем что и как индексировать, а также как отдавать результаты поиска.
Создадим конфигурационный файл для нашего поиска по блогу /home/sphinx/sphinx.conf:
source adw0rd_wp { # Параметры подключения к БД type = mysql sql_host = localhost sql_user = user sql_pass = password sql_db = database_name sql_port = 3306 # Установим кодировку для работы с БД sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 # Запрос выборки данных для индексации sql_query = SELECT ID as post_id, post_title, post_content FROM wp_posts WHERE post_type = 'post' # Запрос доп. информации для вывода результата (используется утилитой "search") sql_query_info = SELECT * FROM wp_posts WHERE ID = $id # Время простоя (sleep) перед посылкой запросов серверу (предназначен для разгрузки сервера БД) # Если установите "= 1000", то засыпание будет длится 1 секунду sql_ranged_throttle = 0 } index adw0rd_wp { # Использовать соответствующий source-блок настроек при индексации source = adw0rd_wp # Путь до файлов индекса path = /home/sphinx/data/adw0rd_wp # Способ хранения индекса (none, inline, extern) # Подробнее docinfo = extern # Memory lock ( mlock = 0 # Использование английского и русского стемминга morphology = stem_enru # Минимальная длина индексируемого слова min_word_len = 2 # Установка используемой кодировки 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 # Минимальная длина инфикса (префикс в том числе) min_infix_len = 2 # Использовать оператор усечения "*" ( enable_star = 1 } indexer { # Максимальный лимит используемой памяти RAM mem_limit = 32M } searchd { # Адрес сервера address = 127.0.0.1 # Порт port = 3312 # Лог log = /home/sphinx/log/searchd.log # Лог запросов query_log = /home/sphinx/log/query.log # Таймаут на соединение с сервером (в секундах). При истечении времени происходит обрыв read_timeout = 5 # Максимальное кол-во потомков от процесса max_children = 30 # Путь до pid-файла pid_file = /home/sphinx/log/searchd.pid # Максимальное кол-во результатов выдачи max_matches = 1000 }
В новых версиях SphinxSearch надо использовать:listen = 127.0.0.1:3312
Вместо# Адрес сервера address = 127.0.0.1 # Порт port = 3312
Разберем используемые нами SQL-запросы:
# Запрос выборки данных для индексации sql_query = SELECT post_title, post_content FROM wp_posts WHERE post_type = 'post'
Тут мы выбираем заголовки и содержимое статей таблицы постов блога, при этом надо указать что типа поста - "post" (это та самая версия поста, которая считается опубликованной и текущей, так как есть еще ревизионные подверсии постов).
# Запрос доп. информации для вывода результата (используется утилитой "search") sql_query_info = SELECT * FROM `wp_posts` WHERE `ID` = $id
Этот запрос применяется для вывода дополнительных данных результатов поиска используемый утилитой коммандной строки "search".
Индексация
Укажем в качестве конфига созданный нами конфигурационный файл:
# indexer --config /home/sphinx/sphinx.conf --all
Для обновления текущего индекса используйте "--rotate", он добавит к созданному индексу новые данные, а измененные соответственно изменит.
# indexer --config /home/sphinx/sphinx.conf --rotate
P.S. Если индексация не удалась, пишите комментарии к статье, посмотрим что случилось... :)
Использование поиска
Для поиска в консоли есть утилита "search":
# search --config /home/sphinx/sphinx.conf искомая комбинация
Запуск поискового сервера
Для работы с поисковым сервером, нам надо его запустить:
# searchd --config /home/sphinx/sphinx.conf
Далее, мы сможем использовать Sphinx API.
Использование Sphinx API для PHP
Для работы со Sphinx API необходимо подключить файл sphinxapi.php, вы можете найти эту библиотеку в поставке с дистрибутивом. Например для установки из портов FreeBSD - путь "/usr/ports/textproc/sphinxsearch/work/sphinx-0.9.8.1/api/sphinxapi.php", а для Windows - "sphinx\api\sphinxapi.php".
А теперь напишем скрипт для работы с проиндексируемыми данными поисковика, то есть для запросов искомых слов и вывода результатов поиска!
<html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> <title>Sphinx search for Wordpress</title> </head> <body> <form action="" method="get"> <input name="s" size="40" value="<?php echo @$_GET['s'];?>" /> <input type="submit" value="Искать!" /> </form> <?php if(isset($_GET['s']) and strlen($_GET['s']) > 2) { // Подключаем sphinx-api require_once ("sphinxapi.php"); // Искомая комбинация $string = $_GET['s']; // Создаем объект клиента для Sphinx API $sphinx = new SphinxClient(); // Подсоединяемся к Sphinx-серверу $sphinx->SetServer('localhost', 3312); // Совпадение по любому слову $sphinx->SetMatchMode(SPH_MATCH_ANY); // Результаты сортировать по релевантности $sphinx->SetSortMode(SPH_SORT_RELEVANCE); // Задаем полям веса (для подсчета релевантности) $sphinx->SetFieldWeights(array ('post_title' => 20, 'post_content' => 10)); // Результат по запросу (* - использование всех индексов) $result = $sphinx->Query($string, '*'); // Если есть результаты поиска, то if ($result && isset($result['matches'])) { // Соединяемся с БД mysql_connect('localhost', 'user', 'password'); mysql_select_db('adw0rd_wp'); // Устанавливаем кодировки mysql_query('SET NAMES utf8'); mysql_query('SET CHARACTER SET utf8'); // Получаем массив ID постов блога $ids = array_keys($result['matches']); // Выводим посты отсортированные по релевантности $id_list = implode(',', $ids); $sql = ' SELECT `ID`, `post_title`, `post_content` FROM `wp_posts` WHERE `ID` IN ('.$id_list.') ORDER BY FIELD(`ID`, '.$id_list.')'; $resource = mysql_query($sql); // Выводим результаты поиска echo '<ol>'; while ($result = mysql_fetch_assoc($resource)) { echo '<li><span><a href="/?p='.$result['ID'].'">'.$result['post_title'].'</a></span><div>'.mb_substr(htmlspecialchars($result['post_content']), 0, 400).'</div>'; } echo '</ol>'; } } ?> </body> </html>
Документация по Sphinx API для PHP:
Резюме
За короткое время нам удалось развернуть быстрейший "поисковый сервис своими руками", с возможностями полнотекстового поиска. Демонстрация работы: .
По всем вопросам, касающемся этой статьи пишите в комментарии.
P.S. Если вам не знакомы слова: "стемминг", "инфикс", "словоформа" и т.д., то существует проект Википедия, в которой можно с легкостью об этом узнать!

Комментарии
ужас.... так то это, столько слов а на деле все за пару минут поднимается)) сфинкс акуенен
привет! пытаюсь поднять под windows xp. Так вот, я хочу попробывать поиск по базе, которая дается в качестве примера, где уже все настроенно. Там еще есть файл с SQL запросом, который создает таблицу documents и заполняет ее данными. Так вот при поиске через search я ввожу такую команду:
а оно выдает:
что это за файл? и почему test1, я же написал просто test?
А ты как индексировал? И какой у тебя путь до конфига получился?
Имхо намного пижже, чем Яндекс-сервер! Убедился на личном опыте)
А заказ на поднятие сфинкса для сайта возьмешь?
Zona, согласен, мне тоже больше нравится :)
aktuba, для какого сайта?
Свой сервер? Виртуальный?
Какой бюджет?
пиши на x11org@gmail.com
adw0rd: свои сервера, сайт nnm.ru =). Бюджет - хотелось бы у тебя услышать.
путь к конфигу у меня получился "c:\Program Files\sphinx\bin\sphinx.conf". И еще такой вопрос. Я пытаюсь выполнить индексацию. Делаю так:
C:\Program Files\sphinx\bin>indexer --all
Sphinx 0.9.8-release (r1533)
Copyright (c) 2001-2008, Andrew Aksyonoff
using config file './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.152 sec, 1267.04 bytes/sec, 26.26 docs/sec
indexing index 'test1stemmed'...
FATAL: failed to open @CONFDIR@/data/test1stemmed.spl: No such file or directory, will not index. Try --rotate option.
в чем проблема? И как выставить @CONFDIR@ ? Где она прописывается?
aktuba, бюджет зависит от кол-ва данных и структуры поиска, я еще не могу представить это, без малейшего ТЗ. Но я заинтересован :)
А почему бы видео не записать как что делалось, небыло бы вопросов?
adw0rd: постучи в аську, plz: 255261508
У меня аськи нет :( http://adw0rd.ru/contacts
Если у тебя нет скайпа и жаббера, то могу в принципе восстановить аську
Есть скайп: aktuba. Есть и куча жабберов, но я ими не пользуюсь. Можешь добавить aktuba@qip.ru, но не обещаю, что контакт сохранится =)
aktuba, добавил тебя в скайпе и в жаббер :)
smackthat, укажи полный путь до каталога "/data/", там хранятся индексы. У меня в конфиге написано как это делать, ты читал внимательно?
шас еще раз прочту
smackthat, видео можно, сегодня попробую снять, но не обещаю :)
Может при следующих выпусках сниму...
разобрался, ищет через утилиту search. Вот осталось через php попробовать. А видео было б воопще клево!
в общем попробывал, но страничка зависает, непойму почему. Делаю так:
Просто как будто загружается, но ничего не происходит, что это может быть?
также попробывал через обычный php, без фреймворка. Точно как у тебя в примере. таже ситуация - страничка подвисает. Проверил сервисы - SphinxSearch есть. Но при его ручном запуске выдает ошибку - Cant start service on local machine
теперь запустил через консоль сам демон и оно выдало такое:
This program (CLI search) is for testing and debugging purposes only;
it is NOT intended for production use.
C:\Program Files\sphinx\bin>searchd
Sphinx 0.9.8-release (r1533)
Copyright (c) 2001-2008, Andrew Aksyonoff
WARNING: forcing --console mode on Windows
using config file './sphinx.conf'...
creating server socket on 127.0.0.1:3312
accepting connections
// в этом месте была значительная пауза
caught SIGTERM, shutting down
shutdown complete
Дай полностью свой конфиг
а это нормально что порты не совпадают?
source articles
{
sql_port = 3306
}
searchd
{
port = 3312
}
smackthat, первый порт - SQL, второй - Sphinx
ясно. А в чем проблема не знаешь? В переменную Path добавил путь к папке bin, но не пашет.
Сейчас посмотрю конфиг...
>Прописать патх нужно для вызова search, searchd, indexer, без прописывания полного
>пути...
а вот оно что))) не силен я в этих консольных штуках...
>Сейчас посмотрю конфиг...
жду)))
smackthat, а ты создал каталог "c:\Program Files\sphinx\bin\data"?
да, и после индексации в нем появились файлы articles с разными форматами sp*
smackthat, проверял работу SQL-запросов? Я просто протестил с твоими конфигами, все нормально!
Ты так в точности запускаешь? Если нет, покажи как именно.
и еще там текст, в общем ищет
теперь другой результат, так как раньше конфиг был в папке bin. Что делать?
adw0rd, так держать! Еще один замечательный программерско-админский пост!
это просто случайно скопировал, считай что последней строки нет. А можно как-то деинсталировать сервис, а потом повторно установить?
smackthat,
Snowcore, спасибо! :)
при попытке остановить пишет что pid файл недоступен или нечитаем. Хотя я и создал каталог, в котором он должен быть. В чем проблема? Также создавал этот пид файл (просто новый пустой файл с этим названием) пишет, что невалидный пид файл. Где его брать? При попытке проинсталировать (--install) пишет что сервис уже запущен.
PID не надо создавать, у меня он вообще не создается. *.pid - это Файл, в который сохраняется PID-процесса.
Спасибо за статью и пояснения я разобрался!
Ура! :)
А что за ошибка при индексации - column '1' has no name ?
Ошибка из-за строки
работает только если выбираем одно поле as его новое имя, типа
Почему же не обрабатывает нормальный запрос?
splash, покажите source полнстью
Какая версия sphinx и mysql у вас? Только точнее, пожалуйста.
sphinx-0.9.8.1-win32
mysql 5.1.31
база в utf8
Думаю проблема с Win-версией, я под Windows не устанавливал Sphinx.
Посмотрите http://sphinxsearch.com/forum/view.html?id=937
Это я уже видел, но не могу найти библиотеку libmysql.dll от mysql 5.0.xx отдельно от дистриба общего...
http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-noinstall-5.0.83-win32.zip/from/http://gd.tuwien.ac.at/db/mysql/ разве тут вы не нашли?
Слишком огромный архив выкачивать ради одной dll...
Библиотеку нашёл, через exe всё работает, но при запуске через php выполняются следующие строки
на последней строке повисает минуты на 2 и без каких-либо ошибок и сообщений завершает работу, '1' выводится, '2' - нет.
Может из-за той же библиотеки, подменяю libmysql.dll в папке mysql - ничего не меняется, может нужна php_mysql.dll от старой версии...
splash, у меня этот архив качается 2 минуты. Вот ваша библиотека: http://1dfile.ru/get/2c5b91fca2ce752759aea959c3c08d03/libmysql.dll
Спасибо за ссылку, но у меня такая же dll.
В общем всё решилось, глючил searchd, повисал при запуске, хотя висело окно с надписью ожидаю подключений... перегрузил всё что можно - заработало.
И библиотека вообще не при чём, при поиске через php она не используется.
Так теперь у вас все работает?
Да, спасибо!
Дело осталось за тестированием...