Заметки по Sphinx (примеры на Sphinx PHP API)

Столкнувшись с медленными выборками в MySQL, начал осваивать Sphinx и его особенности. Работаю со sphinx через sphinxphpapi.php, который находится в официальном дистрибутиве Sphinx. По мере того, как буду сталкиваться с интересными задачами, буду пополнять список заметок. Задавайте вопросы в комментарии, постараемся решить их вместе.

Касаемо установки Sphinx и тонкостей его настройки можно легко найти как в официальной документации, так и на сторонних ресурсах. Возможно, напишу по этому поводу отдельную статью, если будет такая необходимость.

1. Допустим, у вас есть список товаров, которые находятся в разных категориях. Нам нужно получить минимальную цену, максимальную цену и среднюю цену в категории. Обычный SQL выглядел бы так:

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

В sphinx возможно получить эти же параметры

Мы получим набор записей, у которых будут непонятные, но ожидаемые значения. А дело кроется за малым и об этом нам гласит документация, до которой я добрался почему-то не в первую очередь

Starting with version 0.9.9-rc2, aggregate functions (AVG(), MIN(), MAX(), SUM()) are supported when using GROUP BY.

Группировать надо по полю, для которого значение в выборке будет везде одинаковое значение. В нашем случае это cat_id. А что если нам надо сделать подсчет сделать во всех записях, но полей с одинаковыми значениями нет? Просто делаем небольшой трюк.

Как видно, мы добавили новое поле q, которое всегда будет равно единице и группируем по нему.

2. Данный пункт можно отнести к предыдущему. Если у нас не указана цена для товара и поле в таблице имеет NULL, то при выборке значения этих полей будет приравнено к 0. Соответственно это существенно меняет выдачу среднего и, возможно, минимального значения цены в выборке. Если у Вас отсутствуют товары с ценой, равной 0, то смело можно дописать к выборке вот такой код:

Мы просто исключаем все записи, цена в которых равна 0. Тривиально, но довольно практично.

3. Если у записи есть некоторый набор тегов и при фильтрации по некоторым из них

в результате получим все записи, у которых встречается хотя бы одно из значений — 10,11,14. Чаще надо отсортировать так, чтобы нашлись записи, у которых присутствуют все значения одновременно, для этого мы присваиваем фильтр для каждого значения в отдельности:

В таком случае будут найдены записи, у которых присутствуют все три тега одновременно