Mongoose populate:如何在获取父集合记录时获取其子记录

在开发 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


纠错反馈