Mongoose 是 Node.js 中最常用的 ORM 框架之一,它可以让我们通过定义模型和 Schema 的方式,快速且灵活地操作 MongoDB 数据库。Mongoose 中的子文档功能,可以让我们更加方便地建立复杂的数据模型关系,但是在使用时也需要了解一些最佳实践。
嵌套子文档的基本使用
在 Mongoose 中,我们可以通过在 Schema 中定义嵌套的子 Schema,来实现文档的嵌套,比如下面这个例子:
// www.javascriptcn.com code example
const mongoose = require('mongoose')
const { Schema } = mongoose
const subSchema = new Schema({
name: String,
age: Number
})
const mainSchema = new Schema({
title: String,
content: String,
sub: subSchema
})
const MainModel = mongoose.model('Main', mainSchema)上面的代码中,我们定义了两个 Schema,一个是 subSchema,一个是 mainSchema,其中 mainSchema 中的 sub 字段指向了 subSchema,即启用了嵌套子文档的功能。我们可以通过下面的方式来创建一个文档:
// www.javascriptcn.com code example
const data = {
title: 'main title',
content: 'main content',
sub: {
name: 'sub name',
age: 18
}
}
const main = new MainModel(data)
main.save()上面的代码中,我们通过传入一个包含嵌套子文档的对象 data,来创建了一个主文档 main。在创建过程中,Mongoose 会自动将 sub 字段保存为一个子文档,也就是嵌套在主文档中。
同时,我们也可以使用查找操作来查询嵌套子文档,例如:
MainModel.findOne({ 'sub.name': 'sub name' }).exec((err, result) => {
console.log(result)
})上面的代码中,我们通过 findOne 方法来查询 sub.name 字段等于 'sub name' 的文档。这里的 sub.name 就是查询嵌套子文档的基本语法,表示查找主文档中 sub 字段内的 name 字段。
嵌套子文档的操作
在上面我们已经知道,Mongoose 中的子文档就是嵌套在文档中的一个普通对象。因此,我们可以像操作一个普通对象一样来操作子文档。
添加子文档
我们可以通过如下方式来给主文档添加子文档:
main.sub = { name: 'new sub name', age: 20 }
main.save()这里的 main.sub 是一个子文档对象,可以直接重新赋值。
删除子文档
删除子文档也是一样的,可以直接将子文档对象设为 null 或者 undefined:
main.sub = null main.save()
更新子文档
对子文档进行更新时,有两种方式:
- 直接修改子文档对象的属性,然后保存主文档
- 使用
UpdateOne来更新主文档中的子文档字段
第一种方式的代码如下:
main.sub.name = 'updated sub name' main.save()
这里直接修改了子文档中的 name 字段,然后再执行主文档的 save 方法来保存。
第二种方式的代码如下:
MainModel.updateOne({ _id: main._id }, { 'sub.name': 'updated sub name' }, (err, result) => {
console.log(result)
})这里使用了 Mongoose 中的 updateOne 方法,将 _id 等于主文档的 _id 的文档中的 sub.name 字段更新为 'updated sub name'。
嵌套子文档的最佳实践
使用嵌套子文档可以让我们创建复杂的数据模型关系,但同时也需要注意以下几点最佳实践:
1. 避免过度嵌套
过度嵌套会导致数据冗余,影响查询性能。因此,在建立文档结构时,应该尽量减少子文档的嵌套层数。
2. 不要使用循环嵌套
循环嵌套指的是子文档中包含了它本身的情况,这种情况下会导致查询时无限递归,容易出现死循环。
3. 使用 populate 避免嵌套查询
查询嵌套子文档时,如果嵌套层数较多,会导致查询性能下降。这时,我们可以使用 populate 方法,通过关联集合来获取嵌套文档的数据。
4. 将常用的子文档提取出来
如果某个子文档在多个文档中都被使用到,可以考虑将它提取出来,拆分为独立的集合,然后通过关联来使用它。
示例代码
下面是一个具体的示例,展示了如何使用嵌套子文档来建立带有评论功能的博客模型。
// www.javascriptcn.com code example
const mongoose = require('mongoose')
const { Schema } = mongoose
const CommentSchema = new Schema({
title: String,
content: String
})
const ArticleSchema = new Schema({
title: String,
content: String,
comments: [CommentSchema]
})
const ArticleModel = mongoose.model('Article', ArticleSchema)
const data = {
title: 'article title',
content: 'article content',
comments: [
{ title: 'comment 1 title', content: 'comment 1 content' },
{ title: 'comment 2 title', content: 'comment 2 content' }
]
}
const article = new ArticleModel(data)
article.save()上面的代码中,我们定义了一个 ArticleSchema,其中 comments 字段包含了嵌套的 CommentSchema。在创建文章时,我们通过包含 comments 对象数组,来同时创建多个评论。
ArticleModel.findOne({ _id: article._id }).populate('comments').exec((err, result) => {
console.log(result)
})上面的代码中,我们使用了 populate 方法来获取文章的评论信息,这里的 'comments' 参数就是关联的集合名。通过这种方式,可以避免嵌套查询的性能问题。
以上就是关于 Mongoose 中嵌套子文档的使用及最佳实践的详细内容。在使用时,请注意最佳实践,以便更好地利用子文档功能。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d79b09a941bf7134d9da27