Sphinx

Использование системы полнотекстового поиска Sphinx с поддержкой морфологии позволяет добиться высокой скорости индексации и поиска, а также снижения потребления ресурсов сервера.

Установка Sphinx

Sphinx доступен на большинстве платформ, исчерпывающая информация доступна на сайте производителя - установка на Debian и Ubuntu, установка на CentOS и RedHat, установка на Windows.

Для использования мы рекомендуем версию 2.2.10 и старше.

Конфигурирование Sphinx

В конфигурационный файл sphinx.conf внесите новый индекс, в данном примере он называется hostcms:

index hostcms {
    type = rt
    path = /var/lib/sphinx/hostcms
    rt_mem_limit = 64M
    morphology = stem_enru, soundex
    rt_field = title
    rt_field = text
    rt_attr_string = title
    rt_attr_timestamp = datetime
    rt_attr_string = url
    rt_attr_uint = size
    rt_attr_uint = inner
    rt_attr_multi = siteuser_group_id
    rt_attr_uint = module
    rt_attr_uint = module_id
    rt_attr_uint = module_value_type
    rt_attr_uint = module_value_id
    rt_attr_uint = site_id
}

Путь размещения индекса path может варьироваться в зависимости от используемой ОС. Не забудьте проверить соответствие владельцев директории, указанной в пути, и пользователя, от которого работает searchd.

В секции searchd настройте опцию listen, которая задается в формате listen = ( address ":" port | port | path ) [ ":" protocol ]

searchd
{
    listen = localhost:9312:mysql41
    ...
}

Далее перезагрузите searchd и проверьте наличие соединения:

/etc/init.d/searchd restart

Проверьте корректность соединения с Sphinx:

mysql -h 127.0.0.1 -P 9312

В конфигурационном файле модуля поиска в секции default укажите использования драйвера sphinx и задайте параметры:

<?php

return array (
    'default' => array(
        'driver' => 'sphinx',
        'database' => 'sphinx',
        'index' => 'hostcms'
    ),
    'modules' => array(
        0 => 'Structure',
        1 => 'Informationsystem',
        2 => 'Forum',
        3 => 'Shop',
        4 => 'Helpdesk',
        5 => 'Siteuser'
    )
);

В конфигурационном файле баз данных добавьте параметры нового соединения sphinx, указанного выше в опции database:

<?php

return array(
    'default' => array(
       ...
    ),
    'sphinx' => array(
        'driver' => 'pdo',
        'host' => '127.0.0.1:9312',
        'database' => NULL
    )
);

Удаление индекса при внесении изменений в sphinx.conf

В случае изменения конфигурационного файла sphinx.conf мы рекомендуем остановить searchd, удалить файлы индекса (в данном примере файлы hostcms* в /var/lib/sphinx) и запустить searchd.

Использование морфологических словарей

Морфологические словари позволяют улучшить качество поиска, т.к. вместо нахождения основы слова используется нормальная словарная форма.

Слово Стеммер Словарь
Диплом Дипл Диплом
Диплома Диплом Диплом
Груша Груш Груша

Создайте директорию /etc/sphinx/dic/ и загрузите в нее требуемые словари.

В конфигурационный файл sphinx.conf внесите следующие изменения:

index hostcms {
    ...
    #morphology = stem_enru, soundex
    morphology = lemmatize_ru_all, lemmatize_en_all
    ...
}

indexer
{
    ...
    lemmatizer_cache = 64M
}

common
{
    lemmatizer_base = /etc/sphinx/dic/
}

Перезагрузите searchd и проверьте работу:

/etc/init.d/searchd restart

Использование собственного атрибута с поисковым весом элемента

В случае необходимости вносить изменения в результаты поиска на основе собственных весов, например, разместить товары, которых нет в наличии, в самом конце поисковой выдачи, вы можете использовать собственное поле, в которое будете вносить вес, а затем задать формулу расчета веса при поиске.

Внесем в конфигурационный файл после после rt_attr_uint = site_id добавим новое поле rt_attr_float = myweight (также см. выше "Удаление индекса при внесении изменений в sphinx.conf").

В приведенном ниже примере для товаров, которые отсутствуют на складе, устанавливается myweight в 0, а для товаров в наличии 1. Затем используется формула расчета веса, в которой к рассчитанном Sphinx-ом весу прибавляется myweight*10.

class Sphinx_Observer
{
	static public function onAfterPrepareQueryBuilder($object, $args)
	{
		$queryBuilder = $args[0];

		$queryBuilder->columns('myweight');
	 }

	static public function onAfterPrepareValues($object, $args)
	{
		$aValues = $args[0];
		$oPage = $args[1];

		// Товар магазина
		if ($oPage->module == 3 && $oPage->module_value_type == 2)
		{
			$oShop_Item = Core_Entity::factory('Shop_Item', $oPage->module_value_id);

			$myweight = $oShop_Item->getRest() <= 0
				? 0
				: 1;
		}
		else
		{
			$myweight = 1;
		}

		$aValues[] = $myweight;

		return $aValues;
	}

	static public function onBeforeExecuteFind($object, $args)
	{
		$oSearch_Sphinx_QueryBuilder_Select = $args[1];

		// http://sphinxsearch.com/docs/current/sphinxql-select.html
		// http://sphinxsearch.com/docs/current/formulas-for-builtin-rankers.html
		/*
		SPH_RANK_PROXIMITY_BM25 = sum(lcs*user_weight)*1000+bm25
		SPH_RANK_BM25 = bm25
		SPH_RANK_NONE = 1
		SPH_RANK_WORDCOUNT = sum(hit_count*user_weight)
		SPH_RANK_PROXIMITY = sum(lcs*user_weight)
		SPH_RANK_MATCHANY = sum((word_count+(lcs-1)*max_lcs)*user_weight)
		SPH_RANK_FIELDMASK = field_mask
		SPH_RANK_SPH04 = sum((4*lcs+2*(min_hit_pos==1)+exact_hit)*user_weight)*1000+bm25 
		*/
		//$oSearch_Sphinx_QueryBuilder_Select->option('ranker', "expr('sum(lcs*user_weight)*1000+bm25')")
		//$oSearch_Sphinx_QueryBuilder_Select->option('ranker', "expr('sum((word_count+(lcs-1)*max_lcs)*user_weight)+myweight*2')");
		$oSearch_Sphinx_QueryBuilder_Select->option('field_weights', "(title=2)");
		$oSearch_Sphinx_QueryBuilder_Select->option('ranker', "expr('sum(lcs*user_weight) + myweight*10')");
	 }
}

Core_Event::attach('Search_Controller_Sphinx.onAfterPrepareQueryBuilder', array('Sphinx_Observer', 'onAfterPrepareQueryBuilder'));
Core_Event::attach('Search_Controller_Sphinx.onAfterPrepareValues', array('Sphinx_Observer', 'onAfterPrepareValues'));
Core_Event::attach('Search_Controller_Sphinx.onBeforeExecuteFind', array('Sphinx_Observer', 'onBeforeExecuteFind'));

Не нашли ответ на свой вопрос в документации? Направьте обращение в службу поддержки или онлайн чат.

Комментарии

  • с Sphinx 3.3.1 и выше

    rt_attr_timestamp заменили на rt_attr_uint
    http://sphinxsearch.com/docs/sphinx3.html#changes-in-3.x

    15.09.2020 08:19:39
    alexpimnev