Nodejs 模型设计方面的问题求助
Nodejs 模型设计方面的问题求助
要做了一个文章发布功能,另外还需要加入评论。 使用MongoDB,就存在两种方案: 一、文章模型和评论模型分开; 二、将评论嵌套到文章模型中。 我想知道哪一种比较合理,另外嵌套文档是否也有_Id属性。
在Node.js项目中设计模型时,选择合适的文档结构对于性能、可维护性和数据一致性至关重要。针对您的需求(文章发布功能和评论),我们可以考虑两种不同的设计方案:分离式设计和嵌套式设计。
方案一:分离式设计
在这种方案下,我们创建两个独立的集合(或集合类)来分别存储文章和评论。这种方式的优点是易于管理和查询,特别是在评论数量较多的情况下。
文章模型 (Article
)
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: String, required: true },
createdAt: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Article', articleSchema);
评论模型 (Comment
)
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
articleId: { type: mongoose.Schema.Types.ObjectId, ref: 'Article', required: true },
commenter: { type: String, required: true },
content: { type: String, required: true },
createdAt: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Comment', commentSchema);
方案二:嵌套式设计
在这种方案下,我们将每个文章的评论直接嵌入到文章文档中。这种方式的优点是可以减少数据库查询次数,但可能会导致文档过大,影响性能。
文章模型 (Article
)
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: String, required: true },
comments: [{
commenter: { type: String, required: true },
content: { type: String, required: true },
createdAt: { type: Date, default: Date.now }
}],
createdAt: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Article', articleSchema);
关于嵌套文档的 _id
属性
嵌套文档默认不会自动生成 _id
属性,除非显式地添加。如果需要为嵌套文档生成 _id
,可以这样做:
comments: [{
_id: false, // 禁用自动生成的_id
id: { type: mongoose.Schema.Types.ObjectId, auto: true }, // 手动定义_id
commenter: { type: String, required: true },
content: { type: String, required: true },
createdAt: { type: Date, default: Date.now }
}]
结论
- 分离式设计适合评论数量多且频繁查询的情况。
- 嵌套式设计适合评论较少且希望减少查询次数的情况。
选择哪种方案取决于具体的应用场景和性能需求。
很可惜嵌入文档没有_id 属性。 看你的功能是什么样子了。 假如需要递归出针对每个评论的回复。那么每次查询都会很繁琐。 嵌入层次太多,接口设计又会太复杂。针对某个功能都不是太难的东西。 难得是针对你自己底层设计接口的复杂。 对于Mongodb这种文本Nosql数据库,我倒是觉得嵌入到每个评论的字段里面更好, 可能修改不是很方便,但是针对评论来说。我觉得读取比修改更加频繁。 当然我是把评论跟文章分开两个表,但是类似这个网站的针对回复的回复我是嵌入到每个回复表的字段去了。
明白了,暂时我还不准备实现多重的回复。 那就让文章和评论分开吧。谢谢了!
还有个问题,如果我想在文章里插入图片,那数据库该怎么保存呢? 图片和文本是否需要分开保存,是把整个信息存入数据库;还是图片存成类似附件形式的,放到静态目录去。
在设计Node.js应用时,特别是与MongoDB结合使用时,选择合适的数据模型设计方案对于系统的性能和可维护性至关重要。根据你的需求(文章发布功能以及评论功能),我们可以探讨一下这两种方案的优缺点,并提供一些示例代码来帮助你理解。
方案一:文章模型和评论模型分开
优点:
- 更好的扩展性和查询灵活性。
- 评论可以独立更新和查询,比如查看某条评论或者更新某条评论。
- 当评论数量非常大时,不会影响到文章本身的性能。
缺点:
- 需要处理更多的关联逻辑,例如外键约束等。
- 查询时需要进行多次请求或复杂的聚合查询来获取文章及其评论。
示例代码:
// 文章模型
const mongoose = require('mongoose');
const ArticleSchema = new mongoose.Schema({
title: String,
content: String,
createdAt: { type: Date, default: Date.now },
});
const Article = mongoose.model('Article', ArticleSchema);
// 评论模型
const CommentSchema = new mongoose.Schema({
articleId: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' }, // 关联文章ID
content: String,
createdAt: { type: Date, default: Date.now },
});
const Comment = mongoose.model('Comment', CommentSchema);
方案二:将评论嵌套到文章模型中
优点:
- 获取文章及评论更方便,只需一次查询即可完成。
- 更容易保持数据一致性,因为评论是文章的一部分。
缺点:
- 数据量较大时会影响性能。
- 更新评论时可能需要重新保存整个文章对象。
示例代码:
const mongoose = require('mongoose');
const ArticleSchema = new mongoose.Schema({
title: String,
content: String,
comments: [
{
content: String,
createdAt: { type: Date, default: Date.now },
}
],
createdAt: { type: Date, default: Date.now },
});
const Article = mongoose.model('Article', ArticleSchema);
关于嵌套文档是否有_id
属性的问题,嵌套文档默认不具有_id
属性。如果你需要为嵌套文档生成唯一的标识符,可以在定义嵌套文档时显式地添加一个_id
字段。
根据上述分析,你可以根据自己的具体需求和业务场景选择适合的方案。