Как получить данные из EAV (entity–attribute–value)?
Привет! База: Postgres 13. Структура бд
https://www.db-fiddle.com/f/fXUsP2utgLneDKcASY3zA5/2
Пытаюсь получить данные (в идеале только с атрибутом указанным в условие where)
SELECT p.id, p.name, json_agg( json_build_object( 'id', eav_attr.id, 'name', eav_attr.name, 'text', eav_text.val, 'real', eav_real.val, 'boolean', eav_boolean.val ) ) AS characteristics, COUNT(*) OVER() AS total FROM product p JOIN category c ON c.id = p.category_id LEFT JOIN eav_entity eav_e ON eav_e.category_id = c.id LEFT JOIN eav_attribute eav_attr ON eav_attr.id = eav_e.eav_attribute_id LEFT JOIN eav_val_text eav_text ON eav_text.product_id = p.id LEFT JOIN eav_val_real eav_real ON eav_real.product_id = p.id LEFT JOIN eav_val_boolean eav_boolean ON eav_boolean.product_id = p.id WHERE eav_text.attribute_id = 2 GROUP BY p.id, p.name |
SELECT p.id, p.name, json_agg( json_build_object( 'id', eav_attr.id, 'name', eav_attr.name, 'text', eav_text.val, 'real', eav_real.val, 'boolean', eav_boolean.val ) ) AS characteristics, COUNT(*) OVER() AS total FROM product p JOIN category c ON c.id = p.category_id LEFT JOIN eav_entity eav_e ON eav_e.category_id = c.id LEFT JOIN eav_attribute eav_attr ON eav_attr.id = eav_e.eav_attribute_id LEFT JOIN eav_val_text eav_text ON eav_text.product_id = p.id LEFT JOIN eav_val_real eav_real ON eav_real.product_id = p.id LEFT JOIN eav_val_boolean eav_boolean ON eav_boolean.product_id = p.id WHERE eav_text.attribute_id = 2 GROUP BY p.id, p.name
но получается это characteristics (последнее значение перезаписывает предыдущие значения своего типа)
[ { "id": 1, "name": "Описание", "text": "свойства продукта", "real": 100.2, "boolean": null }, { "id": 2, "name": "Свойства", "text": "свойства продукта", "real": 100.2, "boolean": null }, { "id": 3, "name": "Цена", "text": "свойства продукта", "real": 100.2, "boolean": null } ] |
[ { "id": 1, "name": "Описание", "text": "свойства продукта", "real": 100.2, "boolean": null }, { "id": 2, "name": "Свойства", "text": "свойства продукта", "real": 100.2, "boolean": null }, { "id": 3, "name": "Цена", "text": "свойства продукта", "real": 100.2, "boolean": null } ]
Т.е. в идеале в characteristics хотелось бы получить
[ { "id": 2, "name": "Свойства", "val": "свойства продукта" } ] |
[ { "id": 2, "name": "Свойства", "val": "свойства продукта" } ]
ну или хотя бы так
[ { "id": 1, "name": "Описание", "text": "описание продукта", "real": null, "boolean": null }, { "id": 2, "name": "Свойства", "text": "свойства продукта", "real": null, "boolean": null }, { "id": 3, "name": "Цена", "text": null, "real": 100.2, "boolean": null } ] |
[ { "id": 1, "name": "Описание", "text": "описание продукта", "real": null, "boolean": null }, { "id": 2, "name": "Свойства", "text": "свойства продукта", "real": null, "boolean": null }, { "id": 3, "name": "Цена", "text": null, "real": 100.2, "boolean": null } ]
Дополнительно:
WHERE eav_text.attribute_id = 2
Это условие должно быть в ON. Либо все джойны, начиная с этого - INNER.
LEFT JOIN eav_entity eav_e ON eav_e.category_id = c.id AND (eav_e.eav_attribute_id = 2 OR eav_e.eav_attribute_id = 1) LEFT JOIN eav_attribute eav_attr ON eav_attr.id = eav_e.eav_attribute_id LEFT JOIN eav_val_text eav_text ON eav_text.product_id = p.id AND (eav_text.attribute_id = 2 OR eav_text.attribute_id = 1) LEFT JOIN eav_val_real eav_real ON eav_real.product_id = p.id AND (eav_real.attribute_id = 2 OR eav_real.attribute_id = 1) LEFT JOIN eav_val_boolean eav_boolean ON eav_boolean.product_id = p.id AND (eav_boolean.attribute_id = 2 OR eav_boolean.attribute_id = 1) |
LEFT JOIN eav_entity eav_e ON eav_e.category_id = c.id AND (eav_e.eav_attribute_id = 2 OR eav_e.eav_attribute_id = 1) LEFT JOIN eav_attribute eav_attr ON eav_attr.id = eav_e.eav_attribute_id LEFT JOIN eav_val_text eav_text ON eav_text.product_id = p.id AND (eav_text.attribute_id = 2 OR eav_text.attribute_id = 1) LEFT JOIN eav_val_real eav_real ON eav_real.product_id = p.id AND (eav_real.attribute_id = 2 OR eav_real.attribute_id = 1) LEFT JOIN eav_val_boolean eav_boolean ON eav_boolean.product_id = p.id AND (eav_boolean.attribute_id = 2 OR eav_boolean.attribute_id = 1)
https://www.db-fiddle.com/f/fXUsP2utgLneDKcASY3zA5/3
Через INNER вообще ничего не находит.
JOIN category c ON c.id = p.category_id LEFT JOIN eav_entity eav_e ON eav_e.category_id = c.id LEFT JOIN eav_attribute eav_attr ON eav_attr.id = eav_e.eav_attribute_id INNER JOIN eav_val_text eav_text ON eav_text.product_id = p.id INNER JOIN eav_val_real eav_real ON eav_real.product_id = p.id INNER JOIN eav_val_boolean eav_boolean ON eav_boolean.product_id = p.id |
JOIN category c ON c.id = p.category_id LEFT JOIN eav_entity eav_e ON eav_e.category_id = c.id LEFT JOIN eav_attribute eav_attr ON eav_attr.id = eav_e.eav_attribute_id INNER JOIN eav_val_text eav_text ON eav_text.product_id = p.id INNER JOIN eav_val_real eav_real ON eav_real.product_id = p.id INNER JOIN eav_val_boolean eav_boolean ON eav_boolean.product_id = p.id
https://www.db-fiddle.com/f/fXUsP2utgLneDKcASY3zA5/4
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос

Для получения данных из EAV (entity–attribute–value) модели вам потребуется выполнить несколько шагов. EAV является гибкой структурой хранения данных, которая позволяет хранить различные атрибуты для каждой сущности в отдельной таблице.
1. Определите сущность, для которой вы хотите получить данные из EAV модели. Например, это может быть продукт, пользователь или любая другая сущность.
2. Изучите структуру вашей EAV модели. Обычно в EAV модели есть три основные таблицы: entity (сущности), attribute (атрибуты) и value (значения).
3. Напишите SQL запрос, который объединяет эти три таблицы и выбирает необходимые данные. Например, если вы хотите получить все атрибуты продукта с идентификатором 1, запрос может выглядеть примерно так:
SELECT attribute.name, value.value FROM entity JOIN value ON entity.id = value.entity_id JOIN attribute ON value.attribute_id = attribute.id WHERE entity.id = 1;
4. Выполните этот запрос в вашей базе данных или используйте ORM (Object-Relational Mapping) для удобной работы с данными.
5. Обработайте полученные данные в вашем приложении. В зависимости от языка программирования, которым вы пользуетесь, вы можете использовать различные методы для работы с данными.
Надеюсь, эта информация поможет вам успешно получить данные из EAV модели. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.