在开发 Web 应用和 API 的时候,我们通常要面临处理关系型数据,比如用户和文章之间的关系,课程和学生之间的关系等等。这时候 Mongoose populate 就可以派上用场了。
在 Mongoose 中,populate 方法可以让我们简单方便地在获取父集合记录时获取其子记录。这个方法真的非常方便,让那些“拿到父记录还要一遍遍地查询子记录”的时代成为历史。
什么是 Mongoose
Mongoose 是 Node.js 的一个开源模块,它是使用 Node.js 连接 MongoDB 最好的模块。Mongoose 可以在异步环境下运行,它定义了很多的模型方法,可以方便地进行数据操作,同时还支持中间件的使用,可以灵活扩展。
何时使用 Mongoose populate
想象一下这样一种简单的数据设计:文章和作者之间是一对多的关系。在查询文章的时候,如果我们还需要查询作者的信息,而且这些信息在不同的集合中,那么原本的查询方式是这样的:
Article.find({}).exec((err, articles) => { if (err) { throw err; } const articleIds = articles.map((article) => article._id); Author.find({ articleId: { $in: articleIds } }).exec((err, authors) => { if (err) { throw err; } const articlesData = articles.map((article) => { const author = authors.find((author) => author.articleId === article._id); return { id: article._id, title: article.title, author: author ? { name: author.name, email: author.email } : null, }; }); res.json(articlesData); }); });
这种查询方式很繁琐,不仅代码量大,还要进行多次查询。如果使用 populate 方法,就可以轻松地查询出文章和其对应的作者信息,示例代码如下:
Article.find({}) .populate('author', 'name email') .exec((err, articles) => { if (err) { throw err; } res.json(articles); });
其中,populate 方法有两个参数。第一个参数是子记录在父记录中的属性名,第二个参数是一个字符串类型的属性列表,表示需要返回的子记录属性。在本例中,我们希望返回作者的姓名和电子邮件地址,因此传入 'name email'。
Mongoose populate 的高级应用
在上面的例子中,populate 方法已经大大简化了查询,但是还可以进一步优化。我们可以使用链式调用语法,来进行更复杂的查询。
假设我们现在需要对文章按作者分组,并且统计每个作者的文章数量。使用 populate 方法,我们可以这样进行查询:
Article.aggregate([ { $lookup: { from: 'authors', localField: 'author', foreignField: '_id', as: 'author' } }, { $addFields: { author: { $arrayElemAt: ['$author', 0] } } }, { $group: { _id: '$author._id', name: { $first: '$author.name' }, email: { $first: '$author.email' }, articleCount: { $sum: 1 } } }, ]) .exec((err, result) => { res.json(result); });
在这里,aggregate 方法用于执行复杂查询,$lookup 和 $group 表示查询操作。其中 $lookup 被用于连接 Article 和 Author 集合,并将结果保存在名为 author 的数组中。使用 $addFields 这个管道操作符,我们可以将 author 数组中的第一个元素修饰为 author 对象,并用 $group 统计文章数量。
总结
Mongoose populate 方法可以让我们在获取父集合记录时获取其子记录,同时可以通过链式调用语法进行更复杂的查询。它能够大幅简化代码,提高查询效率,让我们更专注于业务逻辑的实现。作为前端开发人员,掌握 Mongoose 的这个方法是非常必要的技能。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a22725add4f0e0ffa33fa4