Предыстория
Раньше для поиска по сайту мы использовали обычный fulltext поиск. Но в определенный момент он перестал нас устраивать и мы решили опробовать альтернативную технологию поиска: Sphinx. К сожалению, у сфинкса совсем нет русской документации, поэтому эта статья — аналог статьи Build a custom search engine with PHP, только на русском языке и для моего локального окружения (windows 7, mysql/php)
Статья состоит из 4 частей:
- Краткий рассказ про подготовку базы для поиска.
- Рассказ про первоначальную установку и настройку сфинкса
- Индексирование базы и тестовый поиск из командной строки
- Тестовый поиск из php
1. Подготовим базу данных для поиска
Перед началом использования сфинкса лучше сразу подготовить базу данных для более удобной индексации и поиска.
У меня есть три таблицы: products, companies, categories, соответственно товары, компании и категории товаров. Создадим view, в котором объединим те данные из всех трех таблиц, по которым будет идти поиск:
CREATE OR REPLACE
VIEW `catalog` AS
SELECT p.`id` , p.`id_company` , p.`id_category` , p.`name` , p.`keyword` , p.`short_desc` , com.`name` AS company_name, cat.`name` AS category_name
FROM `products` p
JOIN `categories` cat ON p.id_category = cat.id
JOIN `companies` com ON p.id_company = com.id
WHERE 1
Поиск в моем случае ведется по полям: название, ключевое слово, краткое описание товара, название компании-производителя и название категории товара. В WHERE можно дописать дополнительные условия, например чтобы поиск шел только по активным компаниям и товарам. На этом подготовительные работы с базой данных закончены.
2. Установка Sphinx
Необходимо с оффсайта скачать свежий дистрибутив: www.sphinxsearch.com/downloads.html
Я скачал себе версию Win32 binaries w/MySQL support 1.10 beta. Далее распаковываем содержимое архива в какую-нибудь папку (я распаковал в C:\Sphinx)
Конфигурирование Sphinx
После скачивания и распаковки архива следующий шаг — настройка. Я в качестве основы взял файл sphinx.conf.in
В этом разделе просто буду приводить конфиги с небольшими комментариями, там вроде все понятно. Весь текст из этого раздела лежит в одном файле sphinx.conf.in
Источник данных
# Источник данных для поиска
source catalog
{
# Тип данных
# Доступные типы: mysql, pgsql, mssql, xmlpipe, xmlpipe2, odbc
type = mysql
# Необходимые параметры для подключения к базе данных
sql_host = localhost
sql_user = root
sql_pass =
sql_db = products
sql_port = 3306 # опциональный, по умолчанию 3306
# пред-запрос, выполняется перед выполнением основного запроса на получение данных из базы
# В нашей базе данные хранятся в UTF-8, чтобы поиск по русским символам работал успешно выполним соответсвующий запрос
sql_query_pre = SET NAMES utf8
# запрос, который получает данные документов для поиска
# первым полем обязательно должен идти уникальный положительный ID документа
sql_query = \
SELECT * \
FROM catalog
# поля, по которым может идти группировка, фильтрация и сортировка
sql_attr_uint = id_company
sql_attr_uint = id_category
# document info query, ONLY for CLI search (ie. testing and debugging)
# optional, default is empty
# must contain $id macro and must fetch the document by that id
sql_query_info = SELECT * FROM products WHERE id=$id
}
Параметры индексации товаров
# индекс каталога товаров для поиска
index catalog
{
# Источник данных для индексирования
source = catalog
# Адрес, где будут хранится данные индекса
path = C:\Sphinx/data/catalog
# Индекс с учетом морфологии
morphology = stem_ru
# Минимальная длина слова для индексации
min_word_len = 1
# Кодировка
charset_type = utf-8
}
Настройки поискового демона (службы)
# поисковый демон (служба)
searchd
{
# какой порт и какой протокол "слушает" служба
listen = 9312
# файл с логами
log = C:\Sphinx/log/searchd.log
# файл с логами поисковых запросов
query_log = C:\Sphinx/log/query.log
# PID file, searchd process ID file name
# mandatory
pid_file = C:\Sphinx/log/searchd.pid
}
На этом конфигурирование сфинкса закончено.
Теперь установим нашу службу. Для этого в адресной строке пишем C:\Sphinx\bin\searchd --install --config C:\Sphinx\sphinx.conf.in --servicename SphinxSearch
Служба установлена и должна появится в администрирование — службы. Пока не запускаем — наши данные еще не проиндексированы.
3. Индексирование и тестовый поиск
Теперь в командной строке пишем C:\Sphinx\bin\indexer --all --config C:\Sphinx\sphinx.conf.in. Получаем результат вроде этого:
C:\Users\Iskander> C:\Sphinx\bin\indexer --all --config C:\Sphinx\sphinx.conf.in
Sphinx 1.10-beta (r2420)
Copyright (c) 2001-2010, Andrew Aksyonoff
Copyright (c) 2008-2010, Sphinx Technologies Inc (http://sphinxsearch.com)
using config file 'C:\Sphinx\sphinx.conf.in'...
indexing index 'catalog'...
collected 572 docs, 0.1 MB
sorted 0.0 Mhits, 100.0% done
total 572 docs, 115192 bytes
total 0.380 sec, 303124 bytes/sec, 1505.19 docs/sec
total 2 reads, 0.000 sec, 31.6 kb/call avg, 0.0 msec/call avg
total 9 writes, 0.001 sec, 14.6 kb/call avg, 0.1 msec/call avg
Все, индекс создан. Теперь запускаем нашу службу SphinxSearch и в поисковой строке пишем что нибудь вроде
C:\Sphinx\bin\search --config C:\Sphinx\sphinx.conf.in computer и получаем результат
C:\Users\Iskander> C:\Sphinx\bin\search --config C:\Sphinx\sphinx.conf.in computer
Sphinx 1.10-beta (r2420)
Copyright (c) 2001-2010, Andrew Aksyonoff
Copyright (c) 2008-2010, Sphinx Technologies Inc (http://sphinxsearch.com)
using config file 'C:\Sphinx\sphinx.conf.in'...
index 'catalog': query 'computer': returned 1 matches of 1 total in 0.000 sec
displaying matches:
1. document=1, weight=2812, id_company=2, id_category=1263
id=1
id_company=2
id_category=1263
words:
1. 'computer': 1 documents, 2 hits
Поиск работает!
4. Поиск из php
Ну тут все просто. Проведем, например, поиск по запросу «Computer»
<?php
// Подключим файл с api
include('C:\Sphinx\api\sphinxapi.php');
// Создадим объект - клиент сфинкса и подключимся к нашей службе
$cl = new SphinxClient();
$cl->SetServer( "localhost", 9312 );
// Собственно поиск
$cl->SetMatchMode( SPH_MATCH_ANY ); // ищем хотя бы 1 слово из поисковой фразы
$result = $cl->Query("computer"); // поисковый запрос
// обработка результатов запроса
if ( $result === false ) {
echo "Query failed: " . $cl->GetLastError() . ".\n"; // выводим ошибку если произошла
}
else {
if ( $cl->GetLastWarning() ) {
echo "WARNING: " . $cl->GetLastWarning() . " // выводим предупреждение если оно было
";
}
if ( ! empty($result["matches"]) ) { // если есть результаты поиска - обрабатываем их
foreach ( $result["matches"] as $product => $info ) {
echo $product . "<br />"; // просто выводим id найденных товаров
}
}
}
exit;
Вот собственно и все, мы установили sphinx, проиндексировали нашу базу данных и написали код на php который ищет по нашей базе и выводит id найденных товаров.
Пришло время дальше изучать документацию, настраивать ранжирование как этого требует проект, и вообще продолжать перенос функционала с полнотекстового поиска на сфинкс.
Надеюсь эта статья сможет кому нибудь помочь сделать «быстрый старт» со сфинксом, потому что по-моему очень не хватает нормальных русских статей и документации по этому, довольно сложному, на мой взгляд, продукту.