MongoDB一对多关系
我开始学习MongoDB,有一刻我问自己如何解决MongoDB中的“一对多”关系设计。在搜索过程中,我在其他帖子/文章中发现了很多评论,比如“你在思考关系”。 好的,我同意。会有一些情况,比如信息重复不会成为问题,比如客户订单 但是,假设您有表:ORDERS,它具有客户购买的产品的嵌入细节结构。 因此,出于这样或那样的原因,您需要更改已经嵌入到多个订单中的产品名称(或其他类型的信息) 最后,您必须在MongoDB中执行一对多关系(也就是说,将ObjectID字段作为链接放置到另一个集合),这样您就可以解决这个简单的问题,不是吗? 但每次我发现一些关于这方面的文章/评论,都会说这将是Mongo的一个性能缺陷。这有点令人失望MongoDB一对多关系,mongodb,Mongodb,我开始学习MongoDB,有一刻我问自己如何解决MongoDB中的“一对多”关系设计。在搜索过程中,我在其他帖子/文章中发现了很多评论,比如“你在思考关系”。 好的,我同意。会有一些情况,比如信息重复不会成为问题,比如客户订单 但是,假设您有表:ORDERS,它具有客户购买的产品的嵌入细节结构。 因此,出于这样或那样的原因,您需要更改已经嵌入到多个订单中的产品名称(或其他类型的信息) 最后,您必须在MongoDB中执行一对多关系(也就是说,将ObjectID字段作为链接放置到另一个集合),这样您
在MongoDB中是否有其他方法可以解决/设计此问题而不会出现性能故障?问题在于您过度规范了数据。订单是由客户定义的,客户在给定的时间点居住在特定的地点,并在订购时支付特定的有效价格(在应用程序生命周期内可能会发生重大变化,您必须记录这些参数,以及仅在特定时间点有效的其他几个参数。因此,要记录订单(双关语),您需要保留该特定时间点的所有数据。让我举个例子:
{ _id: "order123456789",
date: ISODate("2014-08-01T16:25:00.141Z"),
customer: ObjectId("53fb38f0040980c9960ee270"),
items:[ ObjectId("53fb3940040980c9960ee271"),
ObjectId("53fb3940040980c9960ee272"),
ObjectId("53fb3940040980c9960ee273")
],
Total:400
}
现在,只要客户和商品的详细信息没有变化,您就可以复制此订单的发送地点、订单上的价格等。但是现在如果客户更改了地址,或者商品的价格发生了变化,您需要在其各自的文档中跟踪这些变化。存储订单将更容易且效率更高,如下所示:
{
_id: "order987654321",
date: ISODate("2014-08-01T16:25:00.141Z"),
customer: {
userID: ObjectId("53fb3940040980c9960ee283"),
recipientName: "Foo Bar"
address: {
street: "742 Evergreen Terrace",
city: "Springfield",
state: null
}
},
items: [
{count:1, productId:ObjectId("53fb3940040980c9960ee300"), price: 42.00 },
{count:3, productId:ObjectId("53fb3940040980c9960ee301"), price: 0.99},
{count:5, productId:ObjectId("53fb3940040980c9960ee302"), price: 199.00}
]
}
通过此数据模型和聚合管道的使用,您有几个优点:
//people
{
_id: 1,
name: 'John Doe',
gender: gender,
city: {
_id: 1,
name: 'NYC',
area: '30'
.....
}
}
现在,这种设计的问题是,如果纽约市显然有多人居住,那么我们已经对城市数据进行了大量复制
可能,对这些数据建模的最佳方法是使用真实链接
//people
{
_id: 1,
name: 'John Doe',
gender: gender,
city: 'NYC'
}
//city
{
_id: 'NYC',
...
}
在这种情况下,people
集合可以链接到city
集合。知道我们没有外键约束,我们必须保持一致。因此,这是一个一对多关系。它需要两个集合。对于小的一对少(也是一对多),关系,如博客文章到评论。评论可以作为数组嵌入到文章文档中
因此,如果真的是一对多,那么两个集合最适合链接。但是对于一对少数人来说,一个集合通常就足够了。我邀请你看看这些博客文章:(以及第1部分和第2部分)别忘了mongodb是一个NoSQL数据库,所以如果你的数据库中有很多这样的关系,你可能应该选择SQL数据库,因为mongodb在这方面的表现总是比较差。这篇博文很好地解释了这一点:@Baptistel Wuaw!感谢你链接的精彩文章。这让我大开眼界,并证实了我的假设是正确的ut MongoDB是对的。正如作者所说:“MongoDB文档告诉您它擅长什么,而不强调它不擅长什么”。所以我觉得最好还是把我的努力放在另一个地方。@BaptisteL:可能是一个好的程序员,但她不是MongoDB专家。读起来好像她只在两个非常简单的MongoDB项目上工作过,做了几个。她嵌套了文档,尽管这是一种多对多关系(剧集/演员)和嵌套了无限元素的数组(社交提要).为她辩护,手册可能没有今天解释的那么好。这个问题更复杂。我找到了一篇解释很好的文章嗨,马库斯,谢谢你花时间回复,但我想我没有解释清楚。我理解你的观点:订单和细节以一定的价格出售,并在某个特定时刻发送到一个地址,我知道n次。如果事实上你的解决方案是正确的,但我一直看到一种关系模式:我们必须使用Id。但我的意思是:假设你的产品名称有一个拼写错误,并且它已经嵌入到许多文档中。因此,在最后,解决方案是有一个Id链接(就像在关系中一样)因此,您可以避免重复数据。那么,使用文档范例有什么意义呢?因为您不会将产品名称添加到其他文档中,而只将在某个时间点有效的产品属性添加到其他文档中,所以这应该不是问题。链接对象不是问题,但必须非常小心地进行
//people
{
_id: 1,
name: 'John Doe',
gender: gender,
city: 'NYC'
}
//city
{
_id: 'NYC',
...
}