我试图了解如何最好地构建MongoDB Schema,因此寻求有关使用子结构(嵌入式文档)与平面数据结构的指南。
假设我们要在MongoDB中存储一个用户帐户。用户只有一个地址,因此我们可以选择以下两种结构之一:
{
_id: String,
username: String,
firstname: String,
surname: String,
email: String,
street: String,
city String,
zip: Number,
}
或
{
_id: String,
name: {
first: String,
last: String,
}
email: String,
address: {
street: String,
city String,
zip: Number,
}
}
每种结构的优缺点是什么?是否存在何时使用子结构或何时使用平面结构的规则?一个人反对另一个人的理由是什么?
提前谢谢!
答案 0 :(得分:0)
MongoDB提供了各种数据建模模式和模式设计,我将分享我的经验,遇到的问题以及不同DB模式的好处。我们将在下面逐一讨论:
嵌入式VS Flat数据结构:在这种情况下,两种模式之间的差异不大,但是在以嵌入式形式存在的数据模型的情况下,我们将类似类型的数据分组,以便使您从任何集合中投影项目数据时,查询变得容易或小。
例如:如果您要获取完整的地址,则在嵌入文档的情况下,您无需单独$ project地址字段;如果要在获取文档时跳过地址字段,则无需跳过地址字段
嵌入式(一对一)VS嵌入式(一对多)::当我们讨论嵌入式文档对平面数据结构的好处时,如果我们的用户拥有更多的信息,那么一个地址,那么我们就需要具有一对多关系的嵌入式文档。
定义一对一和一对多关系的架构如下:
一对一关系模式:
{
_id: String,
name: {
first: String,
last: String,
}
email: String,
address: {
street: String,
city String,
zip: Number,
}
}
一对多关系架构:
{
_id: String,
name: {
first: String,
last: String,
}
email: String,
address: [{ // Embedded address doc with one to many relationship
street: String,
city String,
zip: Number,
}]
}
在一对一关系的情况下,不会对您的查询部分产生太大影响,但是如果您与一对多关系一起使用,查询中的概念将发生很多变化。
例如:由于主要在更新两种数据结构时我们都面临着不同的情况,所以我将分享更新查询之间的区别。
要更新以一对一关系嵌入的数据,只需使用点符号即可。
db.collection.update(
{ _id: 'anyId' },
{ $set: { "address.street": "abc" } }
)
要更新具有一对多关系的嵌入式数据,您需要使用$运算符。在这种情况下,有两种不同的情况。首先,如果要更新子文档的特定元素,然后要更新所有子文档:
情况1的查询将是(使用$ operator):
db.collection.update(
{ 'address.streent': 'abc' },
{ $set: { "address.$.street": "xyz" } }
)
第2种情况的查询将是(使用$[]):
db.collection.update(
{ 'address.streent': 'abc' },
{ $set: { "address.$[]": "xyz" } }
)