Как задать произвольную компоновку фильтров в Sphinx
Итак, речь пойдет о Sphinx'е. Что это такое можно узнать, например, здесь или здесь. Никаких инструкций об установке и настройке поисковой систему куда-либо или как-либо не будет, увы. Рассматривать работу мы будем на базе методов класса sfSphinxClient — часть пакета sfSphinxPlugin для Symfony 1.4
Основными инструментами поиска в Sphinx являются запросы
и фильтры. К моему разочарованию, через методы фильтры нельзя
компоновать с разными логическими условиями, например, (условие1 И условие2) ИЛИ условие3
. Если вы задали фильтр, то
все последущие setFilter при поиске будут сравниваться через И
. Часто, такое поведение не дает решить поставленную
задачу.
Что же делать, чтобы заставить фильтры в Sphinx работать через ИЛИ
? Решение в методе SetSelect.
Через него можно задать произвольную выборку данных из существующего индекса, подобно тому, как это делается в базах
данных. В нашем случае, ключевой является возможность использовать конструкцию IF
:
IF(a <= 2 OR b >= 5, 1, 0) AS cf
"Чудесно, что можно делать произвольные выборки, но чем это может помочь?", — спросите вы. А тем, что теперь мы можем
задать фильтр по результату условия в SELECT cf
в вышеуказанном примере) и получить желаемый результат. Давайте
рассмотрим фрагмент кода, демонстрирующий сложную компоновку фильтров в Sphinx, более наглядно.
// Инициализация клиента
$sphinx = new sfSphinxClient(array('offset' => 0, 'limit' => 1));
// Определяем сложный фильтр
$sphinx->SetSelect('*, IF((a >= 2 OR b <= 5) OR (c != 0 AND c = 10), 1, 0) AS cf');
// Именно здесь мы применяем сложный фильтр к выборке. Обязательно без @ и прочих специальных символов!!!
$sphinx->SetFilter('cf', array(1));
// Получаем результат
$result = $sphinx->getRes();
Можно, также, использовать несколько IF
в одном SELECT
— разделяются запятой и должны , и даже проводить над
результатами различные операции, например:
IF(a >= 2 OR b <= 5, 1, 0) + IF(c != 0 AND c = 10, 5, 0)
Достаточно гибко, хотя наглядная компоновка фильтров, как в том же Elasticsearch, по-моему, для неискушенных удобнее.