如何实现动态属性,同时保持查询清晰有效
我正在尝试为产品和相关的动态产品属性提出数据库/模型设计。然而,在建模部分,我担心我做了一些“错误”的事情,因为我最终使用了大量的联接。基本上,我希望获得一些关于如何实现所需功能的意见,也许通过更简单的设计。 如果有经验的人觉得我错过了一些重要的事情 - 那么请赐教:)
动态产品属性示例:
- 尺码
- 颜色
- 制造商
- 重量
“动态”属性涵盖两个方面,其中一个方面只有一个值,例如等于某个值的权重,或其他示例颜色,其中包含许多不同的值。 除了属性值之外,每个属性还具有独特的语言设置。例如,属性键/值可以根据客户语言而改变。
我的表格结构:
Product
- id
- created
- modified
Product_variants
- id
- product_id
- quantity
- price
Attribute
- id
- visible
- required
- comparable
Attribute_group
- id
- type
Attribute_groups_attributes
- attribute_group_id
- attribute_id
Attribute_group_languages
- id
- attribute_group_id
- name
- locale
Attribute_languages
- id
- attribute_id
- name
- value
- locale
Product_attribute
- product_id
- attribute_id
- group
- variant
查询示例
为了获取最新的产品和匹配的属性,我执行了下面令人讨厌的查询:
SELECT pv.price, pv.special_price, pv.overlay_id, p.id, pv.id variant, pl.url_key, pl.name, UNIX_TIMESTAMP(p.created) created, al.value color_value, a.id color_id,al.name color_name
FROM x_product_attribute pa
INNER JOIN x_attribute_group ag
ON pa.attribute_id = ag.id AND pa.group = 1 AND pa.variant = 0 AND ag.type LIKE 'color%'
INNER JOIN x_attribute_group_languages agl
ON agl.attribute_group_id = ag.id AND agl.locale = :locale
INNER JOIN x_attribute_groups_attributes aga
ON aga.attribute_group_id = pa.attribute_id
INNER JOIN x_product_attribute pa2
ON aga.attribute_id = pa2.attribute_id AND pa2.variant = 1 AND pa2.group = 0
INNER JOIN product_variants pv
ON pa2.product_id = pv.id
INNER JOIN x_attribute_languages al
ON al.attribute_id = pa2.attribute_id AND al.locale = :locale
INNER JOIN x_attribute a
ON a.id = pa2.attribute_id
INNER JOIN products p
ON p.id = pa.product_id
INNER JOIN product_languages pl
ON pl.product_id = p.id
INNER JOIN shop_products sp
ON sp.shop_id = :shop_id AND sp.product_id = pa.product_id
GROUP BY p.id,a.id
ORDER BY p.created DESC,a.sort ASC, p.id DESC
如上所述,有很多 JOINS一个应该相对简单的查询。我可以将其分成更小的查询,但我不确定什么是最有效的 - 同时仍然映射并保持属性的“动态”属性。
I’m trying to come up with a database/model design for product and related dynamic product attributes. However at the modeling part I’m afraid I’m doing something “wrong”, as I end up using A LOT of JOINS. Basically I’m hoping to get some input on how to achieve the desired functionality, perhaps with a more simple design.
Should anyone with experience feel that I missed something of importance - then please enlighten me :)
Examples of dynamic product attributes:
- Size
- Color
- Manufacturer
- Weight
The “dynamic” attribute covers two aspects, one where there’s a single value, like weight that equals some value, or the other example color, which holds a lot of different values.
In addition to the attribute values, each attribute also has unique language settings. E.g. the attribute key/value can change depending on the customer language.
Structure of my tabels:
Product
- id
- created
- modified
Product_variants
- id
- product_id
- quantity
- price
Attribute
- id
- visible
- required
- comparable
Attribute_group
- id
- type
Attribute_groups_attributes
- attribute_group_id
- attribute_id
Attribute_group_languages
- id
- attribute_group_id
- name
- locale
Attribute_languages
- id
- attribute_id
- name
- value
- locale
Product_attribute
- product_id
- attribute_id
- group
- variant
Example of a query
In order to fetch the newest products and matched attributes, I execute the nasty query below:
SELECT pv.price, pv.special_price, pv.overlay_id, p.id, pv.id variant, pl.url_key, pl.name, UNIX_TIMESTAMP(p.created) created, al.value color_value, a.id color_id,al.name color_name
FROM x_product_attribute pa
INNER JOIN x_attribute_group ag
ON pa.attribute_id = ag.id AND pa.group = 1 AND pa.variant = 0 AND ag.type LIKE 'color%'
INNER JOIN x_attribute_group_languages agl
ON agl.attribute_group_id = ag.id AND agl.locale = :locale
INNER JOIN x_attribute_groups_attributes aga
ON aga.attribute_group_id = pa.attribute_id
INNER JOIN x_product_attribute pa2
ON aga.attribute_id = pa2.attribute_id AND pa2.variant = 1 AND pa2.group = 0
INNER JOIN product_variants pv
ON pa2.product_id = pv.id
INNER JOIN x_attribute_languages al
ON al.attribute_id = pa2.attribute_id AND al.locale = :locale
INNER JOIN x_attribute a
ON a.id = pa2.attribute_id
INNER JOIN products p
ON p.id = pa.product_id
INNER JOIN product_languages pl
ON pl.product_id = p.id
INNER JOIN shop_products sp
ON sp.shop_id = :shop_id AND sp.product_id = pa.product_id
GROUP BY p.id,a.id
ORDER BY p.created DESC,a.sort ASC, p.id DESC
As mentioned, there's a lot of JOINS in a query that should be relative simple. I could split this up into smaller queries, but I'm not sure what would be the most effective - while still mapping and keeping the "dynamic" properties of the attributes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我建议使用 NoSQL 解决方案,例如 MongoDB。它将使您的应用程序设计变得更加容易,因为您可以使用简单的名称-值对(就像 JSON 一样)来表示您的产品。
如果你坚持使用 SQL,我认为你会发现你的应用程序和数据库变得难以管理。
I would suggest a NoSQL solution, such as MongoDB. It will make designing your application much easier since you can represent your products with simple name-value pairs (just like JSON).
If you stick with SQL, I think that you will find that your application and database become unmanageable.
虽然像 MongoDB 这样的 NoSQL DB 绝对是更合适的选择,但如果您必须使用 SQL,我建议您学习 EAV 模式并研究 Magento Commerce 的数据库设计。
http://www.magentocommerce.com/wiki/2_-_magento_concepts_and_architecture/magento_database_diagram#the_magento_eav_data_model
这将让您真实地感受到这是如何在生产系统中成功实现的。
While NoSQL DB like MongoDB is definitely a better fit, if you must use SQL, I'll recommend that you go through the EAV pattern and study the database design of Magento Commerce.
http://www.magentocommerce.com/wiki/2_-_magento_concepts_and_architecture/magento_database_diagram#the_magento_eav_data_model
That would give a real world feel for how this has been successfully implemented in production systems.