Товарищи, озадачился вопросом, как сделать умный фильтр товаров, что бы избежать ситуации, када юзер попадает на пустой результат. То бишь, при выборе каких-то опций, те, которые ведут заведомо к пустому результату скрывать или переводить в состояние disable. Вот первый попавшийся пример: http://www.perfekto.ru/catalog/vanny/ Из соображений — при каждом клике делать запрос к БД и «прозванивать» ситуацию, но, ходят слухи, что это делается не так; якобы разок (после каждого добавления товара) генерится некий огромный массив всех возможных комбинаций, который потом и используется для корректировки пользовательского меню-фильтра. Поделитесь вашими мыслями, товарищи.
Спасибо, человек с голубыми глазами. А можно ли получить чуть более развёрнутый ответ или отсылку на чтиво по теме?
ну, можно кешировать, да. А так чтобы заранее всё обсчитать, наверное смысла нету, если у тебя не миллионная аудитория. С чем борешься-то? Или на всякий пожарный решил заморочить себе голову?
Именно так и делается Если у вас добавление товаров происходит раз в сутки, то сделайте так, что мешает? Если у вас товары добавляют пользователи сотнями и тысячами ежечасно, то живые запросы по подсчету количества товаров при каждом изменении номенклатуры будут заметно базу нагружать. В варианте с кешированием каждый час обновляйте кэш с количеством товаров по фильтрам — вот и всё что требуется.
добавлю, что сервер БД сам очень нефигово кеширует запросы. если таблицы, входящие в запрос, не изменялись, повторный вызов того ж запроса выполняется в разы быстрее. поэтому желательно предоставить базе побольше побольше места под временные таблицы.
Спасибо, товарищи, за ответы. Однако ж, заинтересовал способ реализации с помощью массива комбинаций. Я такого ещё не делал, с чем едят его непонятно, хочу освоить. Может кто раскроет тему? Хотя бы ссылкой на чтиво, гуглмугл что-то не кажет ничего интересного, хотя тут скорее я не могу нужным образом сформулировать поисковый запрос, т.к. тема незнакомая вовсе. Похоже именно так, миллионной аудитории нет.
Что вы не можете сформулировать? Факториал числа или что? Математика 11 класс или 1 курс вуза. Если чисел(фильтров) 6 то факторил 720 комбинаций. Каждый опшион +1 к числу для которого смотрите факториал. Если комбинаций мало — можно держать результаты в кэшах. Каждая комбинция это запрос к БД на число строк удовлетворяющих фильтру.
usermuser, считай через group by запрос. Сам недавно научился сему трюку - в 10 раз нагрузку на процессор снизил. Даже без кеширования (а толку фильтры кешировать, тем более при таких масштабах). Причём, где-то здесь, на форуме, и нашёл способ. Очень эффективно работает. Этот движок для магазина, в котором 400к товаров. Первый вариант, без group by на таком количестве товара 30% процессора отхватывал на простое отображение страницы (без нагрузки на сайт), сейчас 300-400 хостов (может уже и больше, не спрашивал у заказчика, но поскольку меня с этим проектом не беспокоят, значит работает как надо) держит. Там приблизительно получается так: Код (Text): select count(id) as c, category_id from products group by category_id Это получается подсчёт товаров в каждой категории. К примеру, у меня там фильтр по производителю - поэтому вместо category_id стоит vendor_id
mkramer, ты пропустил category_id во фразе select. но суть понятна. если цель в том, чтобы узнать какие признаки присутствуют в выборке, достаточно просто сделать group by по этим признакам — без подсчета количества. в результате будет выдан список только тех признаков, которые упоминаются хотябы раз. Код (Text): SELECT x.category FROM (any_subquery_with_field_category) AS x GROUP BY x.category или то же самое через DISTINCT: Код (Text): SELECT DISTINCT x.category FROM (any_subquery_with_field_category) AS x Добавлено спустя 22 минуты 44 секунды: применительно к магазину и набору значений: каждому блоку признаков соответствует одно поле. например Материал Акриловые Квариловые Литой мрамор Стальные Чугунные "Материал" это поле. остальные слова это возможные значения этого поля (SELECT DISTINCT `материал` FROM `item_in_store`). x.category придется заменить на список полей, какие присутствуют в фильтре. Код (Text): SELECT DISTINCT * FROM ( SELECT <список полей фильтра> FROM `items_on_store` WHERE <наложенный фильтр> ) AS x в итоге получим список всех уникальных комбинаций параметров, которые существуют при наложенном фильтре. пункт на странице можно сделать недоступным если он ни разу не встретился в полученной выборке. я подозреваю, что магазин из ссылки в первом посте получает в ответе AJAX буквально список уникальных значений, которые делает enabled: Код (Text): { 'Материал': ['Акриловые', 'Литой мрамор'], 'Производитель': ['Astra Form'], … }
добавочка: полезные функции для получения набора уникальных значений Код (PHP): function getDistinct(array $rows, $field) { $result = []; foreach ($rows as $row) { $result[] = $row[$field]; } return array_values(array_unique($result)); } function getAllDistinct(array $rows) { $result = []; if (!empty($rows)) { $fields = array_keys(reset($rows)); foreach ($fields as $field) { $result[$field] = getDistinct($rows, $field); } } return $result; } здесь $rows это массив строк, полученный из базы, типа так: Код (PHP): while ($row = mysql_fetch_assoc($result)) { $rows[] = $row; }