Undr

На память

Хранение динамического набора атрибутов в базе данных

1 Star2 Stars3 Stars4 Stars5 Stars (3 голосов, средний: 5.00 из 5)
Loading ... Loading ...

with 4 comments

Периодически возникает потребность хранить динамические наборы определенных атрибутов для объектов. Например, в электронном магазине нужно хранить карточку товара, где набор атрибутов может быть разный для разных видов товара. Телефоны, например, имеют размер, вес, поддерживаемые стандарты связи, цветной/черно-белый дисплей; Книги – кол-во страниц, автор, издательство, isbn. Существует несколько способов хранить атрибуты, самые популярные: хранить товар и его атрибуты в общей таблице и шаблон EAV.

С хранением аттрибутов в одной общей таблице все более-менее понятно, а что такое шаблон EAV? Вот его упрощенный вариант (нет указаний о типе атрибута). Создаем пять таблиц: для храненния товаров (items), для хранения групп атрибутов (types), для хранения названий атрибутов (attributes), таблцу для связи групп атрибутов и самих атрибутов (attributes_types) и таблицу для значений атрибутов (values)

CREATE TABLE `values` (
  `item_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `attribute_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `value` tinytext,
  PRIMARY KEY  (`product_id`,`attribute_id`)
) TYPE=MyISAM;
CREATE TABLE `attributes_types` (
  `attribute_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `type_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
  PRIMARY KEY  (`attribute_id`,`type_id`)
) TYPE=InnoDB;
CREATE TABLE `attributes` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` varchar(126) NOT NULL DEFAULT '',
  `abbr` varchar(24) NOT NULL DEFAULT '',
  PRIMARY KEY  (`id`)
) TYPE=InnoDB;
CREATE TABLE `types` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL DEFAULT '',
  PRIMARY KEY  (`id`)
) TYPE=InnoDB;
CREATE TABLE `items` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `type_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  PRIMARY KEY  (`id`)
) TYPE=InnoDB;

Для выборки одного объекта с атрибутами используем два запроса, например, ищем объект с id =6

# Один для выборки объекта
SELECT i.*, t.name type_name
FROM `items` i, `types` t
WHERE i.id = 6 AND i.type_id = t.id

# Другой для выборки его атрибутов
# (значение type_id берем из результатов первого запроса)
SELECT a.name, v.value, v.abbr
FROM `attributes_types` at, `attributes` a, `values` v
WHERE at.attribute_id = a.id AND at.type_id = 1 AND a.id = v.attribute_id AND v.item_id = 6

Для поиска по атрибутам, используем этот запрос:

# Здесь значения a.id, это первичные ключи атрибутов
# по которым осуществляется поиск,
# а v.value - искомые значения
SELECT i.*, v.value, v.abbr, a.name
FROM `items` i, `attributes` a, `values` v
WHERE a.id = v.attribute_id AND p.id = v.item_id AND ((a.id = 1 AND v.value = '100') OR (a.id = 2 AND v.value = '50'))

Написал undr ()

4 сентября 2009 в 18:32

Размещено в Примеры

Метки: , ,

4 Responses to 'Хранение динамического набора атрибутов в базе данных'

Подписаться на комментарии or TrackBack to 'Хранение динамического набора атрибутов в базе данных'.

  1. Спасибо, с этой заметки больше понятно, чем с Википедии. Попробую делать такое с использованием Doctrine.

    Xobb

    9 Ноя 09 at 16:22

  2. Еще взгляните как EAV в Magento реализовали. Много интересного можна подсмотреть.

    Xobb

    9 Ноя 09 at 16:25

  3. Спасибо, посмотрю. Как раз в тему.

    Кстати, еще, наверное, можно использовать MongoDB. В mySQL хранить ключи и описания наборов данных, а сами динамические атрибуты хранить в MongoDB. На днях собираюсь попробовать такой вариант.

    undr

    10 Ноя 09 at 17:54

  4. Мне в Битриксе на эту тему очень нравились инфоблоки, на рельсах кто-нибудь подобное бы реализовал, зачетная штучка бы была.

    woto

    14 июня 10 at 1:26

Оставьте комментарий