Электронная торговля, товары в категориях и просмотр категорий

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

Вот моя основная проблема и краткое описание того, как настроена система: продукты находятся внутри категорий, категории могут быть дочерними элементами другой категории. Таким образом, категория представлена ​​в виде дерева на левой боковой панели веб-сайта.

Пользователь может просматривать любую категорию, даже не являющуюся «конечной» категорией, если пользователь нажимает на неконцевую категорию, такой список должен быть представлен, например, в категории уровня 1 (то же самое применимо к категориям уровня 2):

big category 1
 category level ( 3 or 2 )
  product 1
  product 2
  product 3
 category level ( 3 or 2 ) 

Вещи также должны иметь постраничное отображение и присутствовать по 5 продуктов на каждой странице. Плюс категории должны быть упорядочены так же, как они появляются в меню слева ... моя схема БД такая:

+-------------+    +-------------+
+ category    +    + product     +
+-------------+    +-------------+
+ category_id +    + product_id  +
+ parent_id   +    + category_id + 
+-------------+    +-------------+

Я действительно не могу понять, как мне следует кодировать SQL, чтобы убедиться, что продукт отображается в том порядке, в котором они должны (например, заказ продуктов и категорий имеет меню).

Также меня беспокоит производительность всей установки: если пользователь выберет категорию, не являющуюся «листом», мне придется искать по всей дочерней категории и создать большую категорию IN (id1, id2, id3), и я знаю по многолетнему опыту Оператор IN не работает.

Если кто-то столкнулся с таким же дизайном / проблемой и у вас есть совет, как это сделать, я был бы благодарен.


person RageZ    schedule 29.10.2009    source источник


Ответы (2)


Вы можете использовать дизайн Материализованный путь. Путь к каталогу - это пример материализованного пути. То есть последовательность значений-предков, объединенных вместе, с некоторым символом (обычно «/» или «,»), разделяющим их.

Итак, у вас могут быть категории:

+---------------------------------------------+
| cat_id | Name            | cat_path | depth |
+---------------------------------------------+
|    1   | Electronics     | 1/       |   1   |
|    2   | Digital cameras | 1/2/     |   2   |
|    3   | SLR cameras     | 1/2/3/   |   3   |
|    4   | Audio           | 1/4/     |   2   |
|    5   | Speakers        | 1/4/5/   |   3   |
|    6   | Wall Satellites | 1/4/5/6/ |   4   |
|    7   | Computers       | 1/7/     |   2   |
+---------------------------------------------+

Теперь, если вам нужны все продукты, которые находятся в разделе «Аудио», вы можете выполнить такой запрос:

SELECT p.*, pc.*
FROM Products p JOIN Categories pc ON (p.cat_id = pc.cat_id)
JOIN Categories c ON (pc.cat_path LIKE c.cat_path||'%')
WHERE c.name = 'Audio';

Например, '1/4/5/6' LIKE '1/4/%' истинно, поэтому настенные сателлиты включены. И то же самое для любой другой подкатегории аудио.


Ответьте на ваш вопрос о рендеринге меню: я предполагаю, что вы хотите, чтобы меню отображало: - всех предков выбранной категории - всех братьев и сестер предков выбранной категории

Итак, если вы выберете «Динамики», вы увидите:

  • Electronics
    • Audio
      • Speakers
    • Компьютеры
    • Цифровые камеры

Но вам не нужны потомки компьютеров или цифровых фотоаппаратов (то есть «кузены» динамиков).

SELECT uncle.name, uncle.depth
FROM Categories chosen
JOIN Categories ancestor ON (chosen.cat_path LIKE ancestor.cat_path||'%')
JOIN Categories uncle ON (ancestor.depth = uncle.depth
  AND SUBSTRING(REVERSE(ancestor.cat_path), 3, 100) = SUBSTRING(REVERSE(uncle.cat_path), 3, 100))
WHERE chosen.name = 'Speakers'
ORDER BY uncle.depth, uncle.name;

Я использую трюк для обнаружения дядей: сравниваю пути после удаления последнего элемента. Для этого переверните строку, а затем удалите элемент first. Это должно работать, по крайней мере, в MySQL и MS SQL Server, но REVERSE() не является стандартным и может не переноситься на другие марки СУБД.

Обратите внимание, что вам, вероятно, следует разрешить более одной цифры для каждого элемента в cat_path, и в этом случае смещение подстроки также должно увеличиться.

person Bill Karwin    schedule 29.10.2009
comment
Большое спасибо, Билл, да, это упрощает, просто небольшой подвопрос с этим дизайном, как вы реализуете рендеринг меню категорий? например, показывать вещи в иерархии ‹ul› и ‹li› - person RageZ; 29.10.2009
comment
Спасибо за вашу огромную помощь, думаю, теперь я смогу справиться с этим ;-) - person RageZ; 29.10.2009
comment
Это может быть старым, но заслуживает большего внимания, красивого решения, а также отличной производительности, например, нет необходимости выполнять обход дерева! - person Leonel Becerra; 15.10.2020

С точки зрения производительности это плохой дизайн. Если клиент случайно нажимает на самую верхнюю категорию, вы выполняете запрос всего вашего инвентаря. Это, вероятно, займет неприемлемое количество времени. С точки зрения Интернета, это означает, что клиент теряет терпение, переходит на сайт вашего конкурента и никогда больше не посещает ваш сайт.

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

Я бы также не согласился с самой идеей древовидной навигации как подхода. Это слишком похоже на то, чтобы просить ваших клиентов поиграть в игру «Угадай, как мы составляем инвентарь». Помимо всего прочего, во многих сферах продукт может принадлежать более чем к одной категории, поэтому размещение их в иерархии - процесс произвольный. По крайней мере, вам, вероятно, следует иметь модель данных, которая поддерживает назначение продукта нескольким конечным категориям. (Это может зависеть от характера того, что вы продаете, и детализации ваших категорий).

Если ваш начальник настаивает на своем, у вас все еще есть несколько вариантов повышения производительности запроса. Например, у вас может быть таблица, которая включает все продукты, объединенные всеми их родительскими категориями ...

cat1 product1
cat1 product2
cat1 product3
cat1 product4
cat1 cat1.1 product1
cat1 cat1.1 product2
cat1 cat1.2 product3
cat1 cat1.2 product4
cat1 cat1.1 cat1.1.1 product1
cat1 cat1.1 cat1.1.2 product2
cat1 cat1.2 cat1.2.1 product3
cat1 cat1.2 cat1.2.2 product4

Вам придется поддерживать это с помощью триггеров, или в виде материализованного представления, или с помощью какого-либо другого механизма (в зависимости от того, что предлагает ваш вариант базы данных). Но накладные расходы на его поддержку будут незначительны по сравнению с преимуществами в производительности от отсутствия необходимости повторно собирать иерархию продукта для каждого запроса клиента. К тому же маловероятно, что в вашем инвентаре такая высокая волатильность.

person APC    schedule 29.10.2009
comment
Я согласен с тем, что древовидная структура - это не способ организации каталога. Сейчас становятся популярными системы на основе тегов, и они позволяют продуктам существовать в нескольких местах коллекции. Но тогда вам могут понадобиться иерархические теги. В любом случае ОП не просил кого-то изменить требования, он спросил, как реализовать имеющееся у него требование, а именно организовать категории в виде дерева. - person Bill Karwin; 29.10.2009
comment
@APC да, система тегов была бы лучше, вещи, которые, вероятно, меня спасут, каталог небольшой, так как продукт действительно дорогой, плюс я бы, вероятно, сделал некоторое кеширование этих данных. Я хотел бы иметь возможность изменить способ поведения системы, но переговоры с клиентом уже выполнены, и невозможно вернуться, это то, что происходит, когда во время разговора с клиентами нет разработчика. @ Билл еще раз большое спасибо - person RageZ; 29.10.2009