Nodejs中Mongodb数据库设计使用嵌套还是引用?
Nodejs中Mongodb数据库设计使用嵌套还是引用?
举个例子,一个blog,支持评论。 是使用嵌套方式存储呢,还是引用方式?
使用嵌套方式查询快,但是假如我要更新一个用户的头像网址怎么办?
如果使用引用方式,查询次数可能会有很多。
请大家指导一下,谢谢~
嵌套:
{ “post”: { “id”: 0, “content”: “content”, “comments”: [ { “author”: “author1”, “avator”: “http://…/a.jpg”, “comment”: “comment1” } ] }
引用:
{ “post”: { “id”: 0, “content”: “content”, }
{ “comment”: { “post_id”: “0”, “author”: “author1”, “avator”: “http://…/a.jpg”, “comment”: “comment1” } }
Node.js 中 MongoDB 数据库设计:使用嵌套还是引用?
在设计 Node.js 应用程序中的 MongoDB 数据库时,经常会遇到是否应该使用嵌套文档还是引用外部文档的选择。这个问题的答案取决于你的具体需求以及你对性能、可维护性和扩展性的考虑。
嵌套 vs 引用
嵌套:当你有少量的、相对静态的数据,并且这些数据通常会被一起读取时,使用嵌套文档是一个不错的选择。这种方式可以减少查询次数,从而提高读取性能。
引用:当你需要频繁地更新或删除子文档,或者当子文档数量庞大时,使用引用的方式会更加灵活和高效。引用允许你在不影响其他数据的情况下独立更新子文档。
示例:博客评论系统
假设我们有一个博客系统,每个博客文章都可以有多个评论。我们来看看如何在这两种情况下实现它。
嵌套方式
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
author: { type: String, required: true },
avatar: { type: String, required: true },
comment: { type: String, required: true }
});
const postSchema = new mongoose.Schema({
id: { type: Number, required: true, unique: true },
content: { type: String, required: true },
comments: [commentSchema]
});
const Post = mongoose.model('Post', postSchema);
引用方式
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
postId: { type: Number, required: true },
author: { type: String, required: true },
avatar: { type: String, required: true },
comment: { type: String, required: true }
});
const Comment = mongoose.model('Comment', commentSchema);
// 在 Post 模型中引用 Comment
const postSchema = new mongoose.Schema({
id: { type: Number, required: true, unique: true },
content: { type: String, required: true }
});
postSchema.virtual('comments', {
ref: 'Comment',
localField: 'id',
foreignField: 'postId'
});
const Post = mongoose.model('Post', postSchema);
总结
- 嵌套方式适合于数据量小且不会经常变动的情况。例如,一个博客文章和少量的评论。
- 引用方式更适合数据量大且需要频繁更新的情况。例如,一个用户头像的更新不需要影响所有相关的评论。
选择哪种方式取决于你的具体需求和应用场景。希望这些示例能帮助你做出更好的决策。
这个主要还是要根据你业务来看吧。 一、嵌套方法 有点:快速、高效、简单 缺点:需要定期去更新用户信息,这个频度不好把握。 现有的线上方案,如豆瓣用户的信息修改,是一个星期还是一个月只能修改一次(不太记得了)。所有可以采取这个方案,让用户不要频度太高的更新资料。 解决方案:有个服务定期去更新同步两个文档自己的相关信息。(例如:PV在凌晨3点最低的时候)
二、引用方式 优点:两个文档的数据同步更新。 缺点:查询耗时。如果是个频繁调用的功能,缺点会被放大。
建议: 考虑当前APP的体量和用户的特征。比如可以选择折中的方式,例如采用嵌套方式,可以更新头像时,将频繁调用的数据更新,一般的数据,放到后面定时更新等等。
[@vczero](/user/vczero) 非常详细,感谢!~
[@snowdream](/user/snowdream) 一起追node.js &前端
在Node.js中使用MongoDB进行数据库设计时,选择嵌套(内联)还是引用的方式取决于你的应用场景和性能需求。以下是一些考虑因素以及相应的代码示例。
嵌套方式
优点:
- 查询速度快,因为数据都在同一个文档中。
- 简化了数据的读取过程,不需要多次查询数据库。
缺点:
- 更新一个子文档可能需要更新整个父文档,这会导致较大的写操作。
- 数据冗余增加,可能导致数据一致性问题。
示例代码:
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
author: String,
avatar: String,
comment: String
});
const postSchema = new mongoose.Schema({
id: Number,
content: String,
comments: [commentSchema]
});
const Post = mongoose.model('Post', postSchema);
// 创建新的评论
const newComment = {
author: 'author1',
avatar: 'http://.../a.jpg',
comment: 'comment1'
};
Post.findOneAndUpdate(
{ id: 0 },
{ $push: { comments: newComment } },
{ new: true }
).then(updatedPost => console.log(updatedPost))
.catch(err => console.error(err));
引用方式
优点:
- 更灵活,可以独立更新子文档。
- 减少数据冗余,提高数据一致性。
缺点:
- 多次查询数据库以获取完整数据,性能可能稍差。
- 需要处理多个查询的逻辑。
示例代码:
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
postId: { type: mongoose.Schema.Types.ObjectId, ref: 'Post' },
author: String,
avatar: String,
comment: String
});
const Comment = mongoose.model('Comment', commentSchema);
// 创建新的评论
const newComment = new Comment({
postId: mongoose.Types.ObjectId('somePostId'),
author: 'author1',
avatar: 'http://.../a.jpg',
comment: 'comment1'
});
newComment.save()
.then(savedComment => console.log(savedComment))
.catch(err => console.error(err));
// 查询所有评论
Comment.find({ postId: mongoose.Types.ObjectId('somePostId') })
.then(comments => console.log(comments))
.catch(err => console.error(err));
总结
对于简单的场景,嵌套方式可以提供更好的性能。但对于复杂的应用,特别是当需要频繁更新子文档或减少数据冗余时,引用方式更为合适。根据实际需求选择适合的设计方案。