За последние 24 часа нас посетили 22667 программистов и 1051 робот. Сейчас ищут 744 программиста ...

Умный фильтр товаров

Тема в разделе "Решения, алгоритмы", создана пользователем usermuser, 22 июн 2014.

  1. usermuser

    usermuser Новичок

    С нами с:
    22 июн 2014
    Сообщения:
    5
    Симпатии:
    0
    Товарищи,

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

    Вот первый попавшийся пример: http://www.perfekto.ru/catalog/vanny/

    Из соображений — при каждом клике делать запрос к БД и «прозванивать» ситуацию, но, ходят слухи, что это делается не так; якобы разок (после каждого добавления товара) генерится некий огромный массив всех возможных комбинаций, который потом и используется для корректировки пользовательского меню-фильтра.

    Поделитесь вашими мыслями, товарищи.
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    Массив комбинаций это сила.
     
  3. usermuser

    usermuser Новичок

    С нами с:
    22 июн 2014
    Сообщения:
    5
    Симпатии:
    0
    Спасибо, человек с голубыми глазами. А можно ли получить чуть более развёрнутый ответ или отсылку на чтиво по теме?
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    ну, можно кешировать, да. А так чтобы заранее всё обсчитать, наверное смысла нету, если у тебя не миллионная аудитория.

    С чем борешься-то? Или на всякий пожарный решил заморочить себе голову?
     
  5. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Именно так и делается
    Если у вас добавление товаров происходит раз в сутки, то сделайте так, что мешает? Если у вас товары добавляют пользователи сотнями и тысячами ежечасно, то живые запросы по подсчету количества товаров при каждом изменении номенклатуры будут заметно базу нагружать.
    В варианте с кешированием каждый час обновляйте кэш с количеством товаров по фильтрам — вот и всё что требуется.
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.236
    Адрес:
    там-сям
    добавлю, что сервер БД сам очень нефигово кеширует запросы.
    если таблицы, входящие в запрос, не изменялись, повторный вызов того ж запроса выполняется в разы быстрее. поэтому желательно предоставить базе побольше побольше места под временные таблицы.
     
  7. usermuser

    usermuser Новичок

    С нами с:
    22 июн 2014
    Сообщения:
    5
    Симпатии:
    0
    Спасибо, товарищи, за ответы. Однако ж, заинтересовал способ реализации с помощью массива комбинаций. Я такого ещё не делал, с чем едят его непонятно, хочу освоить. Может кто раскроет тему? Хотя бы ссылкой на чтиво, гуглмугл что-то не кажет ничего интересного, хотя тут скорее я не могу нужным образом сформулировать поисковый запрос, т.к. тема незнакомая вовсе.

    Похоже именно так, миллионной аудитории нет.
     
  8. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Что вы не можете сформулировать? Факториал числа или что?
    Математика 11 класс или 1 курс вуза.
    Если чисел(фильтров) 6 то факторил 720 комбинаций. Каждый опшион +1 к числу для которого смотрите факториал.
    Если комбинаций мало — можно держать результаты в кэшах. Каждая комбинция это запрос к БД на число строк удовлетворяющих фильтру.
     
  9. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.552
    Симпатии:
    1.754
    usermuser, считай через group by запрос. Сам недавно научился сему трюку - в 10 раз нагрузку на процессор снизил. Даже без кеширования (а толку фильтры кешировать, тем более при таких масштабах). Причём, где-то здесь, на форуме, и нашёл способ. Очень эффективно работает. Этот движок для магазина, в котором 400к товаров. Первый вариант, без group by на таком количестве товара 30% процессора отхватывал на простое отображение страницы (без нагрузки на сайт), сейчас 300-400 хостов (может уже и больше, не спрашивал у заказчика, но поскольку меня с этим проектом не беспокоят, значит работает как надо) держит. Там приблизительно получается так:
    Код (Text):
    1.  
    2. select count(id) as c, category_id from products group by category_id
    Это получается подсчёт товаров в каждой категории. К примеру, у меня там фильтр по производителю - поэтому вместо category_id стоит vendor_id
     
  10. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.236
    Адрес:
    там-сям
    mkramer, ты пропустил category_id во фразе select. но суть понятна.

    если цель в том, чтобы узнать какие признаки присутствуют в выборке, достаточно просто сделать group by по этим признакам — без подсчета количества. в результате будет выдан список только тех признаков, которые упоминаются хотябы раз.

    Код (Text):
    1. SELECT x.category
    2. FROM (any_subquery_with_field_category) AS x
    3. GROUP BY x.category
    или то же самое через DISTINCT:
    Код (Text):
    1. SELECT DISTINCT x.category
    2. FROM (any_subquery_with_field_category) AS x
    Добавлено спустя 22 минуты 44 секунды:
    применительно к магазину и набору значений:
    каждому блоку признаков соответствует одно поле. например
    Материал
    • Акриловые
    • Квариловые
    • Литой мрамор
    • Стальные
    • Чугунные
    "Материал" это поле. остальные слова это возможные значения этого поля (SELECT DISTINCT `материал` FROM `item_in_store`).

    x.category придется заменить на список полей, какие присутствуют в фильтре.
    Код (Text):
    1. SELECT DISTINCT *
    2. FROM
    3.   (
    4.     SELECT <список полей фильтра>
    5.     FROM `items_on_store`
    6.     WHERE <наложенный фильтр>
    7.   ) AS x
    в итоге получим список всех уникальных комбинаций параметров, которые существуют при наложенном фильтре.
    пункт на странице можно сделать недоступным если он ни разу не встретился в полученной выборке.

    я подозреваю, что магазин из ссылки в первом посте получает в ответе AJAX буквально список уникальных значений, которые делает enabled:
    Код (Text):
    1. {
    2.   'Материал': ['Акриловые',  'Литой мрамор'],
    3.   'Производитель': ['Astra Form'],
    4. }
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.236
    Адрес:
    там-сям
    добавочка: полезные функции для получения набора уникальных значений

    Код (PHP):
    1. function getDistinct(array $rows, $field)
    2. {
    3.     $result = [];
    4.     foreach ($rows as $row) {
    5.         $result[] = $row[$field];
    6.     }
    7.  
    8.     return array_values(array_unique($result));
    9. }
    10.  
    11. function getAllDistinct(array $rows)
    12. {
    13.     $result = [];
    14.     if (!empty($rows)) {
    15.         $fields = array_keys(reset($rows));
    16.         foreach ($fields as $field) {
    17.             $result[$field] = getDistinct($rows, $field);
    18.         }
    19.     }
    20.  
    21.     return $result;
    22. }
    23.  
    здесь $rows это массив строк, полученный из базы, типа так:
    Код (PHP):
    1. while ($row = mysql_fetch_assoc($result)) { $rows[] = $row; }