Конфигурация Sphinx — рабочий пример для Beget.ru

У хостера Beget.ru при любом тарифе хостинга можно подключить поисковую программу Sphinx в разделе «Сервисы». Чтобы оно заработало, нужно правильно прописать конфиг. Далее, пример минимального конфига.

Исходные данные

База данных не обязательно должна быть на том же хостинге, где и сервис, но для простоты создаём там же. Пусть она содержит таблицу «product».

idnamecategory_idproducer_id

Файл конфига

source catalog
{
	type = mysql
	sql_host = localhost
	sql_user = db_user
	sql_pass = db_pass
	sql_db = db_name
	sql_port = 3306
	sql_query_pre = SET NAMES utf8
	sql_query = \
		SELECT * \
		FROM product
	sql_attr_uint = category_id
	sql_attr_uint = producer_id
}

index catalog
{
	source = catalog
	path = /var/lib/sphinx/data/catalog
	morphology = stem_enru
	min_word_len = 1
}

indexer
{
	mem_limit = 240M
}

searchd
{
	log = /var/log/sphinx/searchd.log
	query_log = /var/log/sphinx/query.log
	pid_file = /var/run/sphinx/searchd.pid
	listen = 9312
	listen = 9306:mysql41
}

Здесь, db_user, db_pass и db_name нужно заменить на реальные.

path, log, query_log и pid_file при сохранении конфига подменяются сервисом, как я понял.

Результаты

Получить данные можно так. Установить Yii2 и его компонент Sphinx. Далее, в контроллере добавляем:

/* Это наверх */
use app\models\Product;
use yii\sphinx\Query;
use yii\db\Expression;

/* А это в экшен */
$query = new Query();
$rows = $query->from('catalog')
    ->match(new Expression(':match', ['match' => '@(name) ' . Yii::$app->sphinx->escapeMatchValue($_GET['s'])]))
    ->all();

$result = [];
foreach ($rows as $row) {
    $result[] = Product::findOne(['id' => $row['id']]);
}     

Здесь, catalog — это имя индекса, name — название колонки в таблице.

Соответственно, если в url добавить get параметр ?s=мочалка
будет результат.

Sphinx — поиск без пробелов

Что если в базе есть некоторая запись, содержащая строку «Доктор Ватсон», и требуется её отдать по запросу «докторватсон». То есть, запрос вводится без пробелов. Как искать?
Вариант, индексировать контент без пробелов. При этом, такой индекс должен дополнять обычный, иначе поиск по формам отдельных слов не будет работать. Таким образом, размер индекса увеличивается. Плохо, с точки зрения производительности и экономии ресурсов, но решает задачу.

Пример:

source default_index
{
	type = mysql
	sql_host = *******
	sql_user = *******
	sql_pass = *******
	sql_db = ********
	sql_port = 3306
	sql_query_pre = SET NAMES utf8
	sql_query = \
		SELECT * \
		FROM product
	sql_attr_uint = category_id
	sql_attr_uint = producer_id
}

source without_spaces
{
	type = mysql
	sql_host = *******
	sql_user = *******
	sql_pass = *******
	sql_db = ********
	sql_port = 3306
	sql_query_pre = SET NAMES utf8
	sql_query = \
		SELECT * \
		FROM product
	sql_attr_uint = category_id
	sql_attr_uint = producer_id
}

index default_index
{
	source = default_index
	type = plain
	path = /var/lib/sphinx/data/default_index
	morphology = stem_enru
	min_word_len = 1
	charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+2E, U+002A
	html_strip = 1
	min_prefix_len = 3
	min_infix_len = 0
	expand_keywords = 1
}

index without_spaces
{
	source = without_spaces
	type = plain
	path = /var/lib/sphinx/data/without_spaces
	morphology = stem_enru
	min_word_len = 1
	charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+2E, U+0020, U+002A
	html_strip = 1
	min_prefix_len = 3
	min_infix_len = 0
	expand_keywords = 1
	ignore_chars = U+0020
}

indexer
{
	mem_limit = 240M
}

searchd
{
	log = /var/log/sphinx/searchd.log
	query_log = /var/log/sphinx/query.log
	pid_file = /var/run/sphinx/searchd.pid
	listen = 9312
	listen = 9306:mysql41
}

Оставьте комментарий