Как хранить товары с различными опциями в БД?

Существует такая задача:

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

Одна из категорий товаров подразумевает под собой некие "подписки" (т.е. товар один, но у него может быть несколько вариантов или опций - 1 месяц, 6 месяцев, 1 год, lifetime). Как хранить всё это в базе данных?

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

Что уже было предложено:
1. Создание отдельной таблицы под каждую категорию товара. Возможно, хорошее решение (т.к. категорий будет в худшем случае 10), однако всё ещё непонятно, как добавлять нужный товар, например, в корзину. Как понять, на какую таблицу ссылаться? Была также идея создания дополнительной универсальной таблицы "StoreItem", содержащей поля "item_id" и "item_category", то есть создание некой неявной связи с другой таблицей (на уровне софта понимаем, к какой таблице принадлежит item_category, и ищем в нужной таблице айди, равный item_id). Вроде должно работать, но мне это решение кажется несколько странным.

2. Создание универсальной таблицы "StoreItem" и дополнительной таблицы "ItemOption". На практике оказалось очень сложно управлять всем этим, да и таблица ItemOption не используется нигде, кроме как в этой категории.

3. Использование NoSQL. Как человек, который с NoSQL базами практически не работал, не совсем понимаю, стоит ли оно того, и если да, то нормальная ли это практика - совмещать реляционную и нереляционную БД? Где хранить корзины, заказы в таком случае?

Какое самое красивое / элегантное / практичное решение?
Заранее спасибо за помощь!
  • Вопрос задан
  • 936 просмотров
Решения вопроса 2
ipatiev
@ipatiev
Потомок старинного рода Ипатьевых-Колотитьевых
В стародавние времена это действительно было проблемой.

И обычно использовался п.2, который называется EAV, и который в нормальном виде (таблица всех атрибутов, таблица всех значений, и таблица-связка товар-атрибут-значение), хотя и является истинно реляционным решением, служил причиной кровавых слез не одного поколения программистов.

Эта ситуация послужила одной из причин появления хранилищ для неструктурированных данных, таких как Монго, которые входят в очень широкую категорию NoSQL.
Но сами по себе "документо-ориентированные базы данных" в качестве основного хранилища - это ад и проклятие, хуже EAV. Если EAV делает адом только работу с атрибутами товаров, то Монга делает проклятием работу со всей БД целиком. Забудьте об этой идее.

Тем более что в последние годы появилось вполне достойное решение: во всех классических СУБД появилась поддержка JSON полей.
То есть таблица товаров будет самая обычная, в которой есть общие поля типа цены, названия и прочее. А свойства хранятся в JSON поле. Беря, таким образом, лучшее из двух миров.

На начальном этапе вы даже сможете делать поиск по атрибутам, используя нативные JSON функции. Но в дальнейшем поиск товаров, а так же фильтрацию по атрибутам на странице категории (так называемый "фасетный поиск") надо будет возложить на специальный поисковый движок (который тоже входит в широкую категорию "NoSQL", хотя ничего общего с документными БД не имеет, и БД, собственно, не является), такой как Эластик или Мантикора.

Главное при этом хранить (либо в коде, либо в таблице категорий) эталонные структуры таких json полей, которые, во-первых, использовать как справочники для заполнения товаров (тупо чтобы помнить, что частота процессора называется freq, а не frequency), и чтобы собственно делать фасетные фильтры.
Ответ написан
@mvv-rus
Настоящий админ AD и ненастоящий программист
Ответ на вопрос "как хранить" зависит от того, какие данные вы будете запрашивать. То есть - от представлений данных, с которыми работает ваша программа (программы). Именно на основе этих представлений синтезируется полная модель даннных, хранящаяся в БД.
В свое время, лет 25 назад, был (может, и сейчас есть) стандартизированный подход, называвшийся IDEF1 (это имя из стандарта) или Entity-RelationShip (это название процедуры), позволявший формальным образом синтезировать из этих, частных, представлений полную модель данных. И были программы, которые позволяли это делать. Я одной такой пользовался, ERwin называлась (AFAIK она жива и сейчас), но, в принципе, нужные процедуры можно выполнять и вручную. Описание процедуры на русском есть, как минимум одно, которое я знаю - в старой книге "Мартин Дж. Организация баз данных в вычислительных..."
Короче, синтез модели ваших данных - это ваша задача, связанная со специфическими вашими задачами.
Судя по информации из вашего вопроса, я могу только сказать, что:
1. этот вариант вам явно не походит: данные из представления "Товары в корзине" включают товары из всех категорий, так что отделные таблицы для каждой категории - это костыль: ходить можно, а бежать - уже нет.
2. В ItemOptions можно хранить данные для всех категорий - достаточно указать в каждой записи дополнительно к идентификатору товара идентификатор категории и идентификатор свойства. Потребуются ещё таблица категорий (идентификатор категории как первичный ключ плюс дополнительная информаци) и таблица свойств для каждой из категорий (идентифкатор свойства как первичный ключ, идентификатор категории - внешний, плюс дополнительная информация). Схема получается не очень уклюжая, но для работы в рамках реляционной модели более-менее годная (я когда-то такую и делал и с ней работал, но это было жутко давно). Насколько для вас такая схема пригодна - зависит от ваших моделей предствалений: например, будете ли вы в Корзине указывать дополнительную информацию из ItemOptions.
3. NoSQL - это название больше коммерческое, а не техничекое: оно включает много разных технологий хранения в БД, единственным общим признаком которых является, что они - не реляционные. Под эту задачу мне видится годным вариант навигационной БД (это где каждая запись содержит физические ссылки на связанные с ней записи): сетевая, например. В настоящее время такие БД иногда ещё проходят под псевдонимом "графовая". Но, опять же, смотрите на нужные вам представления, в данном случае - обращайте внимание на пути доступа к данным (эти самые ссылки): навигационные БД в этом плане не так гибки, как реляционные, и отсутствие нужных ссылок может заставить ходить по кривым путям и убить тем самым производительность.
Но это все теория, а что там сейчас на практике творится - я с уверенностью сказать не могу. Насколько я понимаю, там надо смотреь возможности конкретной СУБД - тем более, что производители часто называют их словом "гибридная", и надо понимать, что в этот гибрид попадает.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Dmtm
Android
классическое решение:
таблица товаров, таблица опций, таблица связей товар-опция
NoSQL не нужен
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы