使用截然不同的需要了解的信息集对产品进行建模并将它们链接到订单项?
我目前正在一个网站上工作,该网站销售各种类型的定制产品。我有一般的标准购物车架构:订单有许多 LineItems,LineItems 有一个产品,但我遇到了一点症结:
假设我们的一个产品是一个球,而我们的一个产品是一盒蜡笔。当人们创建订单时,我们最终创建了可以用一些伪代码表示的项目:
Ball:
attributes:
diameter: decimal
color: foreign_ref_to Colors.id
material: foreign_ref to Materials.id
CrayonBox:
attributes:
width: decimal
height: decimal
front_text: string
crayons: many_to_many with Crayon
...
现在,这些项目是在下订单之前创建并存储在我们的数据库中的。我可以很容易地做到这一点,这样当将商品添加到购物车时,我们可以通过在控制器中从 Ball
或 CrayonBox
进行链接来获取产品名称和价格,生成 LineItem
,但如果我们能为每个行项目提供完整的信息集,那就太好了。
我想到了一些可能的解决方案,但没有一个看起来是理想的:
一:使用中间的“产品信息”链接表,并用它来表示不同的产品,所以我们会得到类似的东西:
LineItem
information: many_to_many with product_information
...
ProductInformation:
lineitem: many_to_many with line_item
name: string
value: string
ProductInformation(name='color', value=$SOMECOLOR)
ProductInformation(name='color', value=$SOMEOTHERCOLOR)
...
问题是产品的每个属性需要表示的数据类型并不都属于同一列类型。我可以用字符串来表示一切,但是$DEITY知道我根本不认为这是一个好的解决方案。
我想到的另一个解决方案是让 LineItem
表对代表产品类型的每个表都有一个外键。不幸的是,这意味着我必须检查控制器中每个外键是否存在。我一点也不喜欢这个,但我喜欢它比将每条数据填充到一种数据类型中然后处理数据库外部的所有转换内容要好一些。
另一种可能的解决方案是将产品数据的表名存储在一个列中,但这可能不是一件好事,不是吗?我失去了数据库将东西链接在一起的能力,这让我觉得类似于在不需要的地方使用 eval()
——而且我们都知道 eval()
> 并不经常需要。
我希望能够说“给我订单项,然后提供该订单项的扩展信息”,并拥有各种产品类型的正确信息集。
那么,那些真正知道他们正在使用数据库模式做什么的人,我应该做什么?我应该如何表达这一点?这似乎是一个相当常见的用例,但我无法通过谷歌搜索找到太多信息——这样的事情有一个共同的模式吗?需要更多信息吗?这不可能超出“您可以为此使用 RDBMS”的范围,不是吗?
编辑:我现在相当确定我想要的是类表继承。在我的个人模型中使用别名来“规范化”每个产品类型的“信息”表的链接。不幸的是,我为此使用的 ORM(Doctrine 1.2)有点卡住了,它不支持类表继承。我也许能够用 Doctrine 的“列聚合”继承来完成类似的事情,但是呃。有人认为我上错树了吗?我查看了EAV,我认为它不太适合这个问题——关于不同产品的每组信息都是已知的,尽管它们从产品类型A到产品类型B可能非常不同。EAV的灵活性可能很好,但这似乎是滥用数据库来解决这样的问题。
I'm currently working on a site that sells products of varying types that are custom manufactured. I've got your general, standard cart schema: Order has many LineItems, LineItems have one Product, but I've run into a bit of a sticking point:
Lets say one of our products is a ball, and one of our products is a box of crayons. While people are creating their order, we end up creating items that could be represented by some psuedocode:
Ball:
attributes:
diameter: decimal
color: foreign_ref_to Colors.id
material: foreign_ref to Materials.id
CrayonBox:
attributes:
width: decimal
height: decimal
front_text: string
crayons: many_to_many with Crayon
...
Now, these are created and stored in our db before an order is made. I can pretty easily make it so that when an item is added to a cart, we get a product name and price by doing the linking from Ball
or CrayonBox
in my controller and generating the LineItem
, but it would be nice if we could provide a full set of info for every line item.
I've thought of a few possible solutions, but none that seem ideal:
One: use an intermediary "product info" linking table, and represent different products in terms of that, so we'd have something like:
LineItem
information: many_to_many with product_information
...
ProductInformation:
lineitem: many_to_many with line_item
name: string
value: string
ProductInformation(name='color', value=$SOMECOLOR)
ProductInformation(name='color', value=$SOMEOTHERCOLOR)
...
The problem with this is that the types of data needed to be represented for each attribute of a product does not all fall under the same column type. I could represent everything with strings, but $DEITY knows I don't even come close to thinking that's a good solution.
The other solution I've thought of is having the LineItem
table have a foreign key to each table that represents a Product type. Unfortunately, this means I would have to check for the existence of each foreign key in my controller. I don't like this very much at all, but I like it marginally better than stuffing every piece of data into one datatype and then dealing with all the conversion stuff outside of the DB.
One other possible solution would be to store the tablename of the product data in a column, but that can't possibly be a good thing to do, can it? I lose the capability of the db to link stuff together, and it strikes me as akin to using eval()
where it's not needed -- and we all know that eval()
isn't really needed very often.
I want to be able to say "give me the line item, and then the extended info for that line item", and have the correct set of information for various product types.
So, people who actually know what they're doing with database schema, what should I be doing? How should I be representing this? This seems like it would be a fairly common use case, but I haven't been able to find much info with googling -- is there a common pattern for things like this? Need more info? This can't possibly be outside of the realm of "you can use a RDBMS for this", can it?
Edit: I'm now fairly certain that what I want here is Class Table Inheritance. with an alias in my individual models to "normalize" the link followed to the "info" table for each product type. Unfortunately, the ORM I'm kinda stuck using for this (Doctrine 1.2) doesn't support Class Table Inheritance. I may be able to accomplish something similar with Doctrine's "column aggregation" inheritance, but egh. Anyone think I'm barking way up the wrong tree? I looked over EAV, and I don't think it quite fits the problem -- each set of information about different products is known, although they might be very different from product type A to product type B. The flexibility of EAV may be nice, but it seems like an abuse of the db for a problem like this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我觉得这非常适合 CouchDB / MongoDB 允许每个“行”包含不同的属性,但允许索引查找。对于严格的关系部分使用 MySQL 并对于不同形状的部分使用“nosql”来构建混合结构应该相当简单。
It strikes me that this is a perfect fit for the likes of CouchDB / MongoDB which allow every 'row' to contain different attributes, yet permits indexed lookups. It should be fairly straightforward to build a hybrid structure using MySQL for the rigid relational parts and 'nosql' for the parts of varying shape.
看看此讨论< /强>。
Take a look at this discussion.
假设:
您正在销售一些特定的产品。也就是说,你知道你卖的是蜡笔,而不是抹刀。客户不会来到您的网站并尝试订购您从未听说过的产品。
您销售的产品具有一组预先存在的属性。即,蜡笔有颜色; crayon_boxes 有宽度、高度、蜡笔...客户不会来到您的网站并尝试指定您从未听说过的属性的值。
实现此目的的一种方法是使用属性字符串(如果您是 RBDM 纯粹主义者,请现在闭上眼睛,直到我告诉您再次睁开眼睛)。因此,表格将如下所示:
然后示例记录将如下所示:
使用类似的内容,解析名称/值对根据需要进或出。
Assumptions:
You have some specific products you're selling. I.e., you know you're selling crayons, but not spatulas. The customer doesn't come to your site and try to order a product you've never heard of.
The products you're selling have a pre-existing set of attributes. I.e., crayons have color; crayon_boxes have width, height, crayons... The customer doesn't come to your site and try to specify the value for an attribute you've never heard of.
One way to do this (if you're a RBDM purist, please close your eyes now until I tell you to open them again) is to use an attribute string. So the table would be like this:
And then a sample record would be like this:
With something like this, parse the name/value pairs in or out as necessary.