Mongodb 子文档结构最佳实践和查询
Mongodb subdocument structure best practices and queries
我见过 2 种主要的子文档架构类型:
{
"cbill@boogiemail:com": {
"outbound": [
{
"name": "First",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
{
"name": "Second",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
],
"inbound" : [
{
"name": "First",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
{
"name": "Second",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
]
}
}
替代结构是:
{
"cbill@boogiemail:com": {
"outbound": {
"First": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
"Second": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
},
"inbound" : {
"First": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
"Second": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
}
}
}
两者的主要区别在于 inbound/outbound 子文档的结构。
Mongo 数据库子文档结构的最佳实践是什么?
在每种情况下,什么样的查询会让我得到指向的子文档:
cbill@boogiemail:com.inbound.Second
?
要添加更多信息:
该集合将包含许多以不同电子邮件地址开头的不同文档,但集合中的每个文档在 inbound/outbound 键下只有几个子文档。
您希望以反映您打算如何使用数据的方式构建您的集合和文档。如果您要执行大量复杂查询,尤其是子文档查询,您可能会发现将文档拆分为单独的集合会更容易。这方面的一个例子是从博客 posts.
中拆分评论
您的评论可以存储为子文档数组:
# Example post document with comment subdocuments
{
title: 'How to Mongo!'
content: 'So I want to talk about MongoDB.',
comments: [
{
author: 'Renold',
content: 'This post, it's amazing.'
},
...
]
}
不过,如果您只想对评论进行复杂查询(例如,从所有 post 中选取最新评论或获取一位作者的所有评论),这可能会导致问题。进行这些复杂的查询时,您最好创建两个集合:一个用于评论,另一个用于 posts.
# Example post document with "ForeignKeys" to comment documents
{
_id: ObjectId("50c21579c5f2c80000000000"),
title: 'How to Mongo!',
content: 'So I want to talk about MongoDB.',
comments: [
ObjectId("50c21579c5f2c80000000001"),
ObjectId("50c21579c5f2c80000000002"),
...
]
}
# Example comment document with a "ForeignKey" to a post document
{
_id: ObjectId("50c21579c5f2c80000000001"),
post_id: ObjectId("50c21579c5f2c80000000000"),
title: 'Renold',
content: 'This post, it's amazing.'
}
这类似于您在关系数据库中存储“外键”的方式。像这样规范化您的文档使得查询评论和 posts 变得容易。此外,由于您正在拆分文档,因此每个文档占用的内存也会减少。但是,trade-off 是您必须在任一文档发生更改时维护 ObjectId
引用(例如,当您 insert/update/delete 评论或 post。)并且因为那里Mongo 中没有事件挂钩,您必须在您的应用程序中进行所有这些维护。
在 other-hand 上,如果您不打算对文档的子文档执行任何复杂查询,您可能会受益于存储整体对象。例如,您可能不会查询用户的偏好:
# Example user document with address subdocument
{
ObjectId("50c21579c5f2c800000000421"),
name: 'Howard',
password: 'naughtysecret',
address: {
state: 'FL',
city: 'Gainesville',
zip: 32608
}
}
稍作修改后从此处 (https://www.tutorialspoint.com/how-to-select-a-specific-subdocument-in-mongodb) 找到答案。
第二个示例(我最感兴趣的那个)的查询是:
find({ "cbill@boogiemail:com.inbound": {$exists: true}},{"cbill@boogiemail:com.inbound.Second":1}).pretty()
这导致:
{
"_id" : ObjectId("6216a9940b84b1a642cb925e"),
"cbill@boogiemail:com" : {
"inbound" : {
"Second" : {
"state" : {
"saved" : "cbill@boogiemail.com",
"edited" : "connie@boogiemail.com",
"status" : "draft"
},
"data" : {
}
}
}
}
}
我不确定这是否是最有效的查询 - 欢迎 post 任何更好的选择。
我见过 2 种主要的子文档架构类型:
{
"cbill@boogiemail:com": {
"outbound": [
{
"name": "First",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
{
"name": "Second",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
],
"inbound" : [
{
"name": "First",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
{
"name": "Second",
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
]
}
}
替代结构是:
{
"cbill@boogiemail:com": {
"outbound": {
"First": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
"Second": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
},
"inbound" : {
"First": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "active"
},
"data": {
}
},
"Second": {
"state": {
"saved": "cbill@boogiemail.com",
"edited": "connie@boogiemail.com",
"status": "draft"
},
"data": {
}
}
}
}
}
两者的主要区别在于 inbound/outbound 子文档的结构。
Mongo 数据库子文档结构的最佳实践是什么? 在每种情况下,什么样的查询会让我得到指向的子文档:
cbill@boogiemail:com.inbound.Second
?
要添加更多信息:
该集合将包含许多以不同电子邮件地址开头的不同文档,但集合中的每个文档在 inbound/outbound 键下只有几个子文档。
您希望以反映您打算如何使用数据的方式构建您的集合和文档。如果您要执行大量复杂查询,尤其是子文档查询,您可能会发现将文档拆分为单独的集合会更容易。这方面的一个例子是从博客 posts.
中拆分评论您的评论可以存储为子文档数组:
# Example post document with comment subdocuments
{
title: 'How to Mongo!'
content: 'So I want to talk about MongoDB.',
comments: [
{
author: 'Renold',
content: 'This post, it's amazing.'
},
...
]
}
不过,如果您只想对评论进行复杂查询(例如,从所有 post 中选取最新评论或获取一位作者的所有评论),这可能会导致问题。进行这些复杂的查询时,您最好创建两个集合:一个用于评论,另一个用于 posts.
# Example post document with "ForeignKeys" to comment documents
{
_id: ObjectId("50c21579c5f2c80000000000"),
title: 'How to Mongo!',
content: 'So I want to talk about MongoDB.',
comments: [
ObjectId("50c21579c5f2c80000000001"),
ObjectId("50c21579c5f2c80000000002"),
...
]
}
# Example comment document with a "ForeignKey" to a post document
{
_id: ObjectId("50c21579c5f2c80000000001"),
post_id: ObjectId("50c21579c5f2c80000000000"),
title: 'Renold',
content: 'This post, it's amazing.'
}
这类似于您在关系数据库中存储“外键”的方式。像这样规范化您的文档使得查询评论和 posts 变得容易。此外,由于您正在拆分文档,因此每个文档占用的内存也会减少。但是,trade-off 是您必须在任一文档发生更改时维护 ObjectId
引用(例如,当您 insert/update/delete 评论或 post。)并且因为那里Mongo 中没有事件挂钩,您必须在您的应用程序中进行所有这些维护。
在 other-hand 上,如果您不打算对文档的子文档执行任何复杂查询,您可能会受益于存储整体对象。例如,您可能不会查询用户的偏好:
# Example user document with address subdocument
{
ObjectId("50c21579c5f2c800000000421"),
name: 'Howard',
password: 'naughtysecret',
address: {
state: 'FL',
city: 'Gainesville',
zip: 32608
}
}
稍作修改后从此处 (https://www.tutorialspoint.com/how-to-select-a-specific-subdocument-in-mongodb) 找到答案。
第二个示例(我最感兴趣的那个)的查询是:
find({ "cbill@boogiemail:com.inbound": {$exists: true}},{"cbill@boogiemail:com.inbound.Second":1}).pretty()
这导致:
{
"_id" : ObjectId("6216a9940b84b1a642cb925e"),
"cbill@boogiemail:com" : {
"inbound" : {
"Second" : {
"state" : {
"saved" : "cbill@boogiemail.com",
"edited" : "connie@boogiemail.com",
"status" : "draft"
},
"data" : {
}
}
}
}
}
我不确定这是否是最有效的查询 - 欢迎 post 任何更好的选择。