Sphinx. Installing, configuring, and using the search engine
Not long ago, I wrote an article called “FreeBSD. Installing and configuring Yandex.Server” and promised in the comments to talk about the Sphinx search engine. This is one of three planned articles about this wonderful search engine; in the next articles, I’ll cover the PHP extension and the MySQL extension.
The operating system we’ll be installing and configuring it on is FreeBSD, but I’ll also give tips for Windows users.
As an example, we’ll develop a search feature for my Wordpress blog. For the most impatient readers, here’s a demonstration of the search engine in action: http://demo.adw0rd.ru/sphinxsearch/.
Installation
Installation is quite straightforward
# cd /usr/ports/textproc/sphinxsearch
# make config
Select:
- “mysql” if you use this DBMS and want to work with its data directly from Sphinx
- “iconv” for support for different encodings
# make install
That’s it, installation is complete!
You can download the source code and Windows versions here: http://sphinxsearch.com/downloads.html. After downloading the Windows version, simply extract the archive and add the full path to the \sphinx\bin directory to the “Path” system variable.
Configuration
Before you can search, you need to index your information. Let’s create our configuration file and specify what to index and how, as well as how to serve search results.
Let’s create a configuration file for our blog search at /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)
# Подробнее http://www.sphinxsearch.com/docs/manual-0.9.8.html#conf-docinfo
docinfo = extern
# Memory lock (http://www.sphinxsearch.com/docs/manual-0.9.8.html#conf-mlock)
mlock = 0
# Использование английского и русского стемминга
morphology = stem_enru
# Минимальная длина индексируемого слова
min_word_len = 2
# Установка используемой кодировки
charset_type = utf-8
# Таблица символов (http://www.sphinxsearch.com/docs/manual-0.9.8.html#conf-charset-table)
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
# Использовать оператор усечения "*" (http://www.sphinxsearch.com/docs/manual-0.9.8.html#conf-enable-star)
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
}
In newer versions of SphinxSearch, you need to use:
listen = 127.0.0.1:3312Instead of
# Адрес сервера address = 127.0.0.1 # Порт port = 3312
Full documentation: http://www.sphinxsearch.com/docs/.
Let’s go over the SQL queries we’re using:
# Запрос выборки данных для индексации
sql_query = SELECT post_title, post_content FROM wp_posts WHERE post_type = 'post'
Here we select article titles and content from the blog’s posts table, specifying that the post type must be “post” (this is the version of the post considered published and current, since there are also revision versions of posts).
# Запрос доп. информации для вывода результата (используется утилитой "search")
sql_query_info = SELECT * FROM `wp_posts` WHERE `ID` = $id
This query is used to display additional search result data in the “search” command-line utility.
Indexing
Let’s specify the configuration file we created as the config:
# indexer --config /home/sphinx/sphinx.conf --all
To update the current index, use “–rotate”; it will add new data to the index we created and update any changed data accordingly.
# indexer --config /home/sphinx/sphinx.conf --rotate
P.S. If indexing fails, leave a comment on the article, and we’ll see what happened… :)
Using search
For searching from the console, there’s the “search” utility:
# search --config /home/sphinx/sphinx.conf искомая комбинация
Starting the search server
To work with the search server, we need to start it:
# searchd --config /home/sphinx/sphinx.conf
After that, we’ll be able to use the Sphinx API.
Using the Sphinx API for PHP
To work with the Sphinx API, you need to include the sphinxapi.php file; you can find this library bundled with the distribution. For example, when installing from FreeBSD ports, the path is "/usr/ports/textproc/sphinxsearch/work/sphinx-0.9.8.1/api/sphinxapi.php", and for Windows, it’s “sphinx\api\sphinxapi.php”.
Now let’s write a script to work with the search engine’s indexed data—that is, to query for search words and display the search results!
<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>
Documentation for the Sphinx API for PHP: http://www.sphinxsearch.com/wiki/doku.php?id=php_api_docs
Summary
In a short time, we’ve managed to deploy a blazing-fast “do-it-yourself search service” with full-text search capabilities. A demonstration in action: http://demo.adw0rd.ru/sphinxsearch/.
If you have any questions about this article, leave them in the comments.
P.S. If you’re unfamiliar with terms such as “stemming”, “infix”, “word form”, and so on, there’s a project called Wikipedia, where you can easily learn about them!
Comments are closed. Read the original discussion in Russian →
