Как представить EAV в CSV?

Предположим, у меня есть модель БД, которая поддерживает значения Entity-Attribute. Если бы у меня было две записи, каждая из которых имела несколько записей EAV, например:

яблоко

  • Размер: маленький, большой
  • Цвет: зеленый, красный

Машина

  • Тип: купе, седан
  • Топливо: дизель, газ

Я мог бы легко сделать CSV для Apple:

product, size, color
apple, small, green
apple, small, red
apple, large, green
apple, large, red

Я мог бы сделать то же самое для автомобиля, тоже.

Проблема в том, что если я хочу, чтобы яблоко и машина были в одном CSV? Должны ли мои заголовки CSV выглядеть так:

product, size, color, type, fuel

Однако это не имеет смысла. Яблоки не имеют типа автомобиля или топлива. И машины не имеют размера и цвета (судя по приведенным мной примерам).

Должен ли я использовать что-то вроде этого:

product
apple, size:small, color:green
apple, size:small, color:red
apple, size:large, color:green
apple, size:large, color:red
car, type:coupe, fuel:diesel
car, type:coupe, fuel:gas
car, type:sedan, fuel:diesel
car, type:sedan, fuel:gas

Потребителю CSV просто нужно знать, что после первого столбца идут пары имя-значение, представляющие EAV.

Что такое хороший подход? Предложения?


person StackOverflowNewbie    schedule 29.01.2015    source источник
comment
Почему бы вам не использовать другой формат? Например. вы можете использовать xls и размещать информацию о разных объектах на разных листах.   -  person dyatchenko    schedule 02.02.2015
comment
Это для вывода API. Изначально он будет выводить JSON, но я также хочу предоставить возможность вывода CSV. Если есть стандарт, я хотел бы использовать его.   -  person StackOverflowNewbie    schedule 02.02.2015


Ответы (2)


Стандартный способ организации EAV:

entity,attribute,value
apple,size,small
apple,size,large
apple,color,green
apple,color,red
car,type,coupe
car,type,sedan
car,fuel,gas
car,fuel,diesel

Объектом является яблоко или автомобиль, каждая строка описывает значение одного атрибута объекта в строке.

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


Скажем, это был модификатор цены в стандартной системе электронной коммерции. Как бы я сказал, что маленькое красное яблоко стоит 2 доллара, а маленькое зеленое яблоко — 1 доллар?

У вас есть две разные сущности, поэтому вам нужно иметь два разных идентификатора сущности:

small-red-apple,price,2
small-green-apple,price,1

Или, что чаще, у вас было бы:

entity,attribute,value
1112,name,small-red-apple
1112,type,apple
1112,size,small
1112,color,red
1112,price,2
2223,name,small-green-apple,
2223,type,apple
2223,size,small
2223,color,green
2223,price,1

То есть объект 1112 описывает (или является) маленькое красное яблоко стоимостью 2 доллара США, а 2223 описывает (или является) маленькое зеленое яблоко стоимостью 1 доллар США.

Проверка данных EAV становится очень сложной. Как вы гарантируете, что, когда «тип» объекта — «яблоко», «размер» — «маленький» или «большой», а цвет — «красный» или «зеленый» (но «автомобиль» может иметь цвета «черный», «белый» и «синий» тоже)? Вы должны быть очень осторожны, чтобы идентифицировать «сущность» в каждой строке таблицы EAV, а затем применимые атрибуты и соответствующие диапазоны значений для атрибутов. Вы можете сделать все это с (одной) таблицей EAV, но это будет беспорядочно.

person Jonathan Leffler    schedule 02.02.2015
comment
Скажем, это был модификатор цены в стандартной системе электронной коммерции. Как бы я сказал, что маленькое красное яблоко стоит 2 доллара, а маленькое зеленое яблоко — 1 доллар? - person StackOverflowNewbie; 02.02.2015
comment
У вас есть две разные сущности, поэтому у вас должны быть два разных идентификатора сущности: small-red-apple,price,2 и small-green-apple,price,1. Или, что чаще, у вас будет: 1112,name,small-red-apple, 1112,type,apple, 1112,size,small, 1112,color,red, 1112,price,2 — и аналогично для 2223,name,small-green-apple, … - person Jonathan Leffler; 02.02.2015
comment
Извините, я не понимаю вашего решения для этого сценария с модификатором цены. Не могли бы вы отредактировать свой ответ, чтобы я мог увидеть ваш новый подход в правильно отформатированном примере, пожалуйста? - person StackOverflowNewbie; 02.02.2015

Это решение, которое я собираюсь реализовать:

product, name_1, value_1, name_2, value_2
apple, size, small, color, green
apple, size, small, color, red
apple, size, large, color, green
apple, size, large, color, red
car, type, coupe, fuel, diesel
car, type, coupe, fuel, gas
car, type, sedan, fuel, diesel
car, type, sedan, fuel, gas

Наверное, это достаточно элегантно. Потребителю CVS просто нужно знать, что пары имя-значение следуют шаблону "имя_x" и "значение_x". Список NVP заканчивается, когда он достигает первых пустых "name_x" и "value_x".

person StackOverflowNewbie    schedule 02.02.2015