SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 06.05.2017 00:03:42

webJunior
Завсегдатай
Зарегистрирован: 30.03.2017
Сообщений: 30

Правильная структура интернет магазина

Здравствуйте, извиняюсь если такая тема уже была.

Вопрос такой:

Есть категории товаров, атрибуты товаров и сами товары. Каждый товар должен иметь индивидуальные атрибуты, а так же должна быть привязка группы атрибутов к категории, например пользователь зашел на страницу фильтра категории "телевизоры", следовательно должен быть поиск по атрибутам Диагональ, Разрешение HD, Поддержка 3D и т.д. Атрибуты могут быть разного типа.

Создал такую структуру:



CREATE TABLE `category` (
  `id` mediumint(8) UNSIGNED NOT NULL,
  `left_key` mediumint(8) UNSIGNED NOT NULL,
  `right_key` mediumint(8) UNSIGNED NOT NULL,
  `level` tinyint(3) UNSIGNED NOT NULL,
  `parent_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `attr_group` (
  `id` mediumint(8) UNSIGNED NOT NULL,
  `type` tinyint(3) UNSIGNED NOT NULL,
  `group_alias` varchar(255) NOT NULL,
  `status` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `category_and_attr_group` (
  `id_category` mediumint(8) UNSIGNED NOT NULL,
  `id_attr_group` mediumint(8) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `attr` (
  `id` int(10) UNSIGNED NOT NULL,
  `group_id` mediumint(8) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `products` (
  `id` int(10) UNSIGNED NOT NULL,
  `parent_id` mediumint(8) UNSIGNED NOT NULL,
  `brand_id` smallint(5) UNSIGNED NOT NULL,
  `first_img_id` int(10) UNSIGNED NOT NULL,
  `price` decimal(10,2) UNSIGNED NOT NULL,
  `status` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 


Дальше не могу понять как создать связь products и attr, так как атрибуты могут быть разного типа.

Подскажите пожалуйста как правильно все это организовать? Спасибо.

Неактивен

 

#2 06.05.2017 00:12:49

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Правильная структура интернет магазина

Для интернет-магазинов часто используется паттерн EAV (entity-attribute-value), если уж мыслить создание интернет-магазина на базе РСУБД (это зачастую не самое лучшее решение).
Или flat-tables, то есть у каждого товара своя табличка.

Посмотрите
http://sqlinfo.ru/forum/viewtopic.php?id=7954
http://sqlinfo.ru/forum/viewtopic.php?id=7130
http://sqlinfo.ru/forum/viewtopic.php?id=6508
http://sqlinfo.ru/forum/viewtopic.php?id=3034


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 11.05.2017 16:43:57

webJunior
Завсегдатай
Зарегистрирован: 30.03.2017
Сообщений: 30

Re: Правильная структура интернет магазина

deadka написал:

Для интернет-магазинов часто используется паттерн EAV (entity-attribute-value), если уж мыслить создание интернет-магазина на базе РСУБД (это зачастую не самое лучшее решение).
Или flat-tables, то есть у каждого товара своя табличка.

Посмотрите
http://sqlinfo.ru/forum/viewtopic.php?id=7954
http://sqlinfo.ru/forum/viewtopic.php?id=7130
http://sqlinfo.ru/forum/viewtopic.php?id=6508
http://sqlinfo.ru/forum/viewtopic.php?id=3034

Спасибо за ответ, составил такую структуру

Атрибуты двух видов:
1) числовые, для поиска BETWEEN
2) Списки значений



CREATE TABLE `lang` (
  `id` tinyint(3) UNSIGNED NOT NULL,
  `title` varchar(3) NOT NULL,
  `lang_locale` varchar(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `category` (
  `id` mediumint(8) UNSIGNED NOT NULL,
  `left_key` mediumint(8) NOT NULL,
  `right_key` mediumint(8) NOT NULL,
  `level` tinyint(3) UNSIGNED NOT NULL,
  `parent_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `lang_category` (
  `id_category` mediumint(8) UNSIGNED NOT NULL,
  `id_lang` tinyint(3) UNSIGNED NOT NULL,
  `title` varchar(120) NOT NULL,
  `descr` varchar(115) NOT NULL,
  `keyw` varchar(115) NOT NULL,
  `text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Структура таблицы `attr`, поле type 1 значит числовой, 2 значит список, attr_unit единица измерения
--

CREATE TABLE `attr` (
  `id` mediumint(8) UNSIGNED NOT NULL,
  `type` tinyint(3) UNSIGNED NOT NULL,
  `attr_alias` varchar(255) NOT NULL,
  `attr_unit` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Структура таблицы `category_attr`. Связь категорий и атрибутов, в поле status выводить ли в фильтре на странице категории
--

CREATE TABLE `category_attr` (
  `id_category` mediumint(8) UNSIGNED NOT NULL,
  `id_attr` mediumint(8) UNSIGNED NOT NULL,
  `status` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `lang_attr` (
  `id_attr` mediumint(8) UNSIGNED NOT NULL,
  `id_lang` tinyint(3) UNSIGNED NOT NULL,
  `title` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Структура таблицы `products_attr`, в id_attr идентификатор атрибута числового типа
--

CREATE TABLE `products_attr` (
  `id_product` int(10) UNSIGNED NOT NULL,
  `id_attr` mediumint(8) UNSIGNED NOT NULL,
  `attr_val` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Структура таблицы `list_attr`, список атрибутов, в id_attr идентификатор атрибута
--

CREATE TABLE `list_attr` (
  `id` mediumint(8) UNSIGNED NOT NULL,
  `id_attr` mediumint(8) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `lang_list_attr` (
  `id_list_attr` mediumint(9) NOT NULL,
  `id_lang` tinyint(4) NOT NULL,
  `title` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Структура таблицы `list_attr_products`. связь списка атрибутов и товаров
--

CREATE TABLE `list_attr_products` (
  `id_list_attr` mediumint(8) UNSIGNED NOT NULL,
  `id_product` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `products` (
  `id` int(10) UNSIGNED NOT NULL,
  `parent_id` mediumint(8) UNSIGNED NOT NULL,
  `articul` varchar(100) NOT NULL,
  `brand_id` smallint(5) UNSIGNED NOT NULL,
  `first_img_id` int(10) UNSIGNED NOT NULL,
  `price` decimal(10,2) UNSIGNED NOT NULL DEFAULT '0.00',
  `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
  `show_main_page` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `lang_products` (
  `id_product` int(10) UNSIGNED NOT NULL,
  `id_lang` tinyint(3) UNSIGNED NOT NULL,
  `title` varchar(255) NOT NULL,
  `descr` varchar(115) NOT NULL,
  `keyw` varchar(115) NOT NULL,
  `text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 


Фильтр товаров


SELECT products.id, products_img.img, products_img.thumb_img, lang_products.title  FROM products  INNER JOIN lang_products ON lang_products.id_product = products.id INNER JOIN category ON products.parent_id = category.id  INNER JOIN products_attr as pr_attr1 ON pr_attr1.id_product = products.id INNER JOIN list_attr_products ON list_attr_products.id_product = products.id LEFT JOIN products_img ON products_img.id = products.first_img_id  WHERE  pr_attr1.id_attr = 4 AND pr_attr1.attr_val BETWEEN 20 AND 100 AND list_attr_products.id_list_attr IN ('1','2') AND  category.id = 3 AND lang_products.id_lang = 2 AND products.status = 1
 


План запроса:

| id   | select_type | table              | type   | possible_keys     | key     | key_len | ref                          | rows | filtered | Extra
       |
+------+-------------+--------------------+--------+-------------------+---------+---------+------------------------------+------+----------+--------------------------+
|    1 | SIMPLE      | category           | const  | PRIMARY           | PRIMARY | 3       | const                        |    1 |   100.00 | Using index
       |
|    1 | SIMPLE      | pr_attr1           | ref    | PRIMARY           | PRIMARY | 3       | const                        |    1 |   100.00 | Using where
       |
|    1 | SIMPLE      | products           | eq_ref | PRIMARY,parent_id | PRIMARY | 4       | qg.pr_attr1.id_product       |    1 |   100.00 | Using where
       |
|    1 | SIMPLE      | list_attr_products | ref    | PRIMARY           | PRIMARY | 4       | qg.pr_attr1.id_product       |    1 |   100.00 | Using where; Using index |
|    1 | SIMPLE      | products_img       | eq_ref | PRIMARY           | PRIMARY | 4       | qg.products.first_img_id     |    1 |   100.00 |
       |
|    1 | SIMPLE      | lang_products      | eq_ref | PRIMARY           | PRIMARY | 5       | qg.pr_attr1.id_product,const |    1 |   100.00 |
       |

Вроде везде используются индексы, не совсем понимаю почему часто не советуют использовать EAV. Скажите пожалуйста, какие могут быть подводные камни и какие есть недочеты в предоставленной выше структуре.

Отредактированно webJunior (11.05.2017 16:57:16)

Неактивен

 

#4 17.05.2017 16:04:19

webJunior
Завсегдатай
Зарегистрирован: 30.03.2017
Сообщений: 30

Re: Правильная структура интернет магазина

А вообще чтобы вы посоветовали, для таких целей все таки использовать nosql (Mongo) или Postgresql (jsonb)? Так же в mysql начиная с 5.7 есть поддержка типа json.

Отредактированно webJunior (17.05.2017 16:04:52)

Неактивен

 

#5 17.05.2017 16:08:52

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Правильная структура интернет магазина

Честно говоря, редко использовал NoSQL решения для задач сложнее чем key=>value.
Да, в mysql 5.7 полноценная поддержка json и json-индексов, в postgre тоже с этим все нормально.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson