我使用 mongodb 来存储多个网站的分析。这些网站每天有数以百万计的访问量,每天有数千个不同的网址。我统计每个URL的访问次数。
现在我需要每天获取前一天的数据。
将每个 URL 存储在其自己的文档中还是将所有 URL 存储在一个文档中的一个对象下更好?
小智 5
多个文档或包含大对象的较少文档
不可避免的是,每个使用 MongoDB 的人都必须在使用带有 id 引用的多个集合或嵌入文档之间进行选择。两种解决方案都有其优点和缺点。学习使用两者:
使用单独的集合
db.posts.find();
{_id: 1, title: 'unicorns are awesome', ...}
db.comments.find();
{_id: 1, post_id: 1, title: 'i agree', ...}
{_id: 2, post_id: 1, title: 'they kill vampires too!', ...}
Run Code Online (Sandbox Code Playgroud)
使用嵌入文档
db.posts.find();
{_id: 1, title: 'unicorns are awesome', ..., comments: [
{title: 'i agree', ...},
{title: 'they kill vampires too!', ...}
]}
Run Code Online (Sandbox Code Playgroud)
单独的集合提供最大的查询灵活性
// sort comments however you want
db.comments.find({post_id: 3}).sort({votes: -1}).limit(5)
// pull out one or more specific comment(s)
db.comments.find({post_id: 3, user: 'leto'})
// get all of a user's comments joining the posts to get the title
var comments = db.comments.find({user: 'leto'}, {post_id: true})
var postIds = comments.map(function(c) { return c.post_id; });
db.posts.find({_id: {$in: postIds}}, {title: true});
Run Code Online (Sandbox Code Playgroud)
选择嵌入文档更加有限
// you can select a range (useful for paging)
// but can't sort, so you are limited to the insertion order
db.posts.find({_id: 3}, {comments: {$slice: [0, 5]}})
// you can select the post without any comments also
db.posts.find({_id: 54}, {comments: -1})
// you can't use the update's position operator ($) for field selections
db.posts.find({'comments.user': 'leto'}, {title: 1, 'comments.$': 1})
Run Code Online (Sandbox Code Playgroud)
一个文档(包括所有嵌入的文档和数组)不能超过 16MB。
单独的集合需要更多的工作
// finding a post + its comments is two queries and requires extra work
// in your code to make it all pretty (or your ODM might do it for you)
db.posts.find({_id: 9001});
db.comments.find({post_id: 9001})
Run Code Online (Sandbox Code Playgroud)
嵌入文档简单快捷(单次查找)
// finding a post + its comments
db.posts.find({_id: 9001});
Run Code Online (Sandbox Code Playgroud)
插入和更新没有太大区别
// separate collection insert and update
db.comments.insert({post_id: 43, title: 'i hate unicrons', user: 'dracula'});
db.comments.update({_id: 4949}, {$set : {title: 'i hate unicorns'}});
// embedded document insert and update
db.posts.update({_id: 43}, {$push: {title: 'lol @ emo vampire', user: 'paul'}})
// this specific update requires that we store an _id with each comment
db.posts.update( {'comments._id': 4949}, {$inc:{'comments.$.votes':1}})
Run Code Online (Sandbox Code Playgroud)
因此,如果您需要选择单个文档、需要对查询进行更多控制或拥有庞大的文档,那么单独的集合是很好的选择。当您需要整个文档、带有 $slice 注释的文档或根本没有注释的文档时,嵌入文档是很好的选择。一般来说,如果您有很多“评论”或者它们很大,那么最好单独收集。较小和/或较少的文档往往更适合嵌入。
请记住,您随时可以改变主意。两者都尝试是最好的学习方式。
| 归档时间: |
|
| 查看次数: |
879 次 |
| 最近记录: |