Розробка сортування товарів для інтернет-магазину

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка сортування товарів для інтернет-магазину
Проста
~1 робочий день
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка сортування товарів для інтернет-магазину

Сортування визначає, що користувач бачить першим. Дефолтна сортування за датою додавання — не стратегія. Правильна сортування за замовчуванням збільшує конверсію: товари з високим рейтингом, добрими запасами та підходящою ціною виходять вперед. Кожен варіант сортування — запит з іншим ORDER BY, кожен вимагає правильного індексу.

Стандартний набір варіантів

Варіант SQL Коментар
Популярність ORDER BY sales_count DESC Потрібен окремий лічильник
Рейтинг ORDER BY rating DESC, reviews_count DESC Подвійна сортування: рейтинг + вага
Ціна: по зростанню ORDER BY price ASC Базовий
Ціна: по спаданню ORDER BY price DESC Базовий
Новинки ORDER BY created_at DESC За датою додавання
Акції ORDER BY discount_percent DESC Першi найбільш вигідні
Релевантність За score поисковика Тільки в режимі пошуку

Дефолтна сортування — як правило, «Популярність» або кастомний «Рейтинг магазину» (ручна сортування merchandise-менеджером).

Зважений рейтинг

Наївна сортування за середнім рейтингом некоректна: товар з одним відгуком на 5 звізд окажется вище товара з 200 відгуками на 4.8. Використовуємо Bayesian average або формулу Wilson score:

-- Bayesian average: (C * m + sum_ratings) / (C + reviews_count)
-- C = prior weight (зазвичай середня кількість відгуків по каталогу)
-- m = prior mean (очікуваний рейтинг без даних, зазвичай 3.0–3.5)

UPDATE products SET
  bayesian_rating = (50 * 3.5 + rating_sum) / (50 + reviews_count)
WHERE id = :id;

Це вичисляємое поле оновлюється при кожному новому відгуку. Індекс по bayesian_rating для швидкої сортування.

Лічильник продаж та популярності

sales_count — кумулятивний лічильник всіх продаж. Проблема: старий популярний товар завжди буде вище нового, який зараз активно купуються.

Рішення — time-decayed popularity score:

-- Оновлюється щодня через cron
UPDATE products SET
  popularity_score = (
    SELECT SUM(quantity * EXP(-0.1 * EXTRACT(DAY FROM NOW() - o.created_at)))
    FROM order_items oi
    JOIN orders o ON oi.order_id = o.id
    WHERE oi.product_id = products.id
      AND o.created_at >= NOW() - INTERVAL '90 days'
  )

Коефіцієнт 0.1 настоюється: більше — сильніше обесцінюються старі продажи, менше — довше «пам'ятає» історію. Для швидкозмінного асортименту (мода, сезонні товари) — більше. Для стабільних категорій (інструменти, побутова техніка) — менше.

Ручна сортування (merchandising)

Менеджер магазину хоче управляти тим, що бачить користувач на початку категорії: просувати новинки, спонсоровані товари, залежавший товар. Для цього потрібен sort_order — ручне числове поле.

Інтерфейс: drag-and-drop список товарів в адміністративному розділі категорії. Технічно — зберігаємо масив product_id у упорядкованому вигляді або sort_order: integer на кожному товарі.

Гібридна сортування: перші N позицій — ручні, решта — за алгоритмом.

ORDER BY
  CASE WHEN sort_order IS NOT NULL THEN 0 ELSE 1 END,
  sort_order ASC NULLS LAST,
  popularity_score DESC

Сортування з Elasticsearch

При використанні Elasticsearch сортування задається в параметрі sort:

{
  "sort": [
    { "popularity_score": { "order": "desc" } },
    { "bayesian_rating": { "order": "desc" } },
    { "_score": { "order": "desc" } }
  ]
}

Для ручної сортування: поле pinned_position з null для неприкріплених. У ES є спеціальний тип запиту pinned — він піднімає конкретні ID в початок результатів без порушення релевантності остальних.

Персоналізована сортування

Продвинутий рівень — показувати кожному користувачу різний порядок на основі його історії. Користувач часто купує Apple — для нього Apple-товари піднімаються вище. Користувач дивився товари в певній ціновій категорії — враховуємо це.

Реалізується через користувальницькі boost-фактори в Elasticsearch:

{
  "query": {
    "function_score": {
      "query": { "term": { "category_id": 14 } },
      "functions": [
        {
          "filter": { "term": { "brand": "apple" } },
          "weight": 2.0  // персональний boost для цього користувача
        }
      ]
    }
  }
}

Boost-фактори вичисляються offline (батч-процес на основі історії) та кешуються в Redis за user_id.

UI компонент сортування

Стандартний select-дропдаун з варіантами. На мобайле — bottom sheet. Поточний варіант сортування відображається в URL (?sort=price_asc) та синхронізується зі станом компонента.

При змінені сортування — запит до API без перезагрузки сторінки, скролл вверх до першого товару. Skeleton-плейсхолдери поки список оновлюється.

Індекси для продуктивності

-- Сортування за ціною
CREATE INDEX ON products (category_id, price ASC) WHERE status = 'active';
CREATE INDEX ON products (category_id, price DESC) WHERE status = 'active';

-- Сортування за датою
CREATE INDEX ON products (category_id, created_at DESC) WHERE status = 'active';

-- Сортування за рейтингом
CREATE INDEX ON products (category_id, bayesian_rating DESC) WHERE status = 'active';

-- Ручна сортування + популярність (гібрид)
CREATE INDEX ON products (category_id, sort_order ASC NULLS LAST, popularity_score DESC);

Кожен додатковий варіант сортування — потенційний окремий індекс. При 8–10 варіантах сортування це суттєво впливає на розмір індексів та швидкість INSERT/UPDATE. Правильне рішення: використовувати ES для складних сортувань, залишити у PostgreSQL тільки простий ORDER BY.

Терміни

  • Базові сортування (ціна, дата, рейтинг, вибір в select): 2–4 робочих дні
  • З зваженим рейтингом та time-decayed popularity: 1 тиждень
  • Ручна merchandising-сортування з drag-and-drop інтерфейсом: +1 тиждень
  • Персоналізація на основі історії користувача: 2–3 тижні (вимагає історії поведінки та офлайн-розрахунків)