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

Денис Толстов
Денис Толстов
  • Сообщений: 2
  • Последний визит: 29 сентября 2025 в 12:39

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

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

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

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

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

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

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

Какое самое красивое / элегантное / практичное решение?
Заранее спасибо за помощь!

Валентин Апанович
Валентин Апанович
  • Сообщений: 4
  • Последний визит: 21 сентября 2025 в 20:12

В стародавние времена это действительно было проблемой.

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

Эта ситуация послужила одной из причин появления хранилищ для неструктурированных данных, таких как Монго, которые входят в очень широкую категорию NoSQL.

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

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

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

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

Главное при этом хранить (либо в коде, либо в таблице категорий) эталонные структуры таких json полей, которые, во-первых, использовать как справочники для заполнения товаров (тупо чтобы помнить, что частота процессора называется freq, а не frequency), и чтобы собственно делать фасетные фильтры. 

Евгений Терехов
Евгений Терехов
  • Сообщений: 3
  • Последний визит: 21 сентября 2025 в 22:34

Ответ на вопрос «как хранить» зависит от того, какие данные вы будете запрашивать. То есть — от представлений данных, с которыми работает ваша программа (программы). Именно на основе этих представлений синтезируется полная модель данных, хранящаяся в БД.

В свое время, лет 25 назад, был (может, и сейчас есть) стандартизированный подход, называвшийся IDEF1 (это имя из стандарта) или Entity-RelationShip (это название процедуры), позволявший формальным образом синтезировать из этих, частных, представлений полную модель данных. И были программы, которые позволяли это делать. Я одной такой пользовался, ERwin называлась (AFAIK она жива и сейчас), но, в принципе, нужные процедуры можно выполнять и вручную. Описание процедуры на русском есть, как минимум одно, которое я знаю — в старой книге «Мартин Дж. Организация баз данных в вычислительных...»

Короче, синтез модели ваших данных — это ваша задача, связанная со специфическими вашими задачами.

Судя по информации из вашего вопроса, я могу только сказать, что:

1. этот вариант вам явно не походит: данные из представления «Товары в корзине» включают товары из всех категорий, так что отдельные таблицы для каждой категории — это костыль: ходить можно, а бежать — уже нет.

2. В ItemOptions можно хранить данные для всех категорий — достаточно указать в каждой записи дополнительно к идентификатору товара идентификатор категории и идентификатор свойства. Потребуются ещё таблица категорий (идентификатор категории как первичный ключ плюс дополнительная информации) и таблица свойств для каждой из категорий (идентификатор свойства как первичный ключ, идентификатор категории — внешний, плюс дополнительная информация). Схема получается не очень уклюжая, но для работы в рамках реляционной модели более-менее годная (я когда-то такую и делал и с ней работал, но это было жутко давно). Насколько для вас такая схема пригодна — зависит от ваших моделей представлений: например, будете ли вы в Корзине указывать дополнительную информацию из ItemOptions.

3. NoSQL — это название больше коммерческое, а не техническое: оно включает много разных технологий хранения в БД, единственным общим признаком которых является, что они — не реляционные. Под эту задачу мне видится годным вариант навигационной БД (это где каждая запись содержит физические ссылки на связанные с ней записи): сетевая, например. В настоящее время такие БД иногда ещё проходят под псевдонимом «графовая». Но, опять же, смотрите на нужные вам представления, в данном случае — обращайте внимание на пути доступа к данным (эти самые ссылки): навигационные БД в этом плане не так гибки, как реляционные, и отсутствие нужных ссылок может заставить ходить по кривым путям и убить тем самым производительность.

Но это все теория, а что там сейчас на практике творится — я с уверенностью сказать не могу. Насколько я понимаю, там надо смотреь возможности конкретной СУБД — тем более, что производители часто называют их словом «гибридная», и надо понимать, что в этот гибрид попадает. 

Юрий Беринцев
Юрий Беринцев
  • Сообщений: 2
  • Последний визит: 29 сентября 2025 в 12:40

Классическое решение: 

таблица товаров, таблица опций, таблица связей товар-опция
NoSQL не нужен

Авторизуйтесь, чтобы писать на форуме.

Заявка на услуги DST

Наш специалист свяжется с вами, обсудит оптимальную стратегию сотрудничества,
поможет сформировать бизнес требования и рассчитает стоимость услуг.

Адрес

Ижевск, ул. Воткинское шоссе 170 Е.
Региональный оператор Сколково. Технопарк Нобель

8 495 1985800
Заказать звонок

Режим работы: Пн-Пт 10:00-19:00

info@dstglobal.ru

Задать вопрос по почте

Укажите ваше имя
Укажите ваше email
Укажите ваше телефон