Article {
"_id" : "A",
"title" : "Hello World",
"user_id" : 12345,
"text" : 'My test article',
"comments" : [
{ 'text' : 'blah', 'user_id' : 654321, 'votes' : [987654]},
{ 'text' : 'foo', 'user_id' : 987654, 'votes' : [12345, 654321] },
...
]
}
这里的基本前提是,我将Comments
嵌套在Article
中.Votes
只适用于Comment
,因此它们被存储 for each Comment
的array.在本例中,我刚刚存储了用户id.如果您想存储更多信息(创建时间等),则可以对一组对象进行投票:
... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ...
如何高效地执行查询:
- 获取文章A、对文章A的 comments 和#每条 comments 的投票数
db.articles.find( { _id : 'A' } )
只需一个查询就可以获取所有信息.你可能需要做一些客户端逻辑来计算每条 comments 的投票数,但这是非常琐碎的.
- 获取用户B对所有文章的所有 comments
db.articles.ensureIndex( { "comments.user_id" : 1 } )
db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
该索引将允许有效地搜索文档中的注释.
目前无法仅从子数组中提取匹配项.这个查询实际上将返回该用户的所有带有 comments 的文章.如果这可能是太多的数据,你可以做一些修剪.
db.articles.find( { "comments.user_id" : 987654 }, { "title" : 1, "comments.user_id" : 1 })
- 获取用户B投票支持的所有 comments
db.articles.ensureIndex( { "comments.votes" : 1 } )
db.articles.find( { "comments.votes" : 987654 } )
同样,这将返回所有文章,而不仅仅是 comments .
这里需要做一个权衡.退回这篇文章似乎我们带回了太多的数据.但是,当你进行查询时,你打算向用户显示什么?
如果没有 comments 本身,获得"comments I've voted for"人的名单并不是非常有用.当然,如果没有文章本身(或者至少只有标题), comments 就没有多大用处.
大多数情况下,查询#3会从Votes
到Comments
再到Articles
转化为一个连接.如果是这样的话,那为什么不把文章带回来呢?