首页 > 解决方案 > 如何计算数组内对象的值的总和,并使用 mongoose 聚合基于该总和添加一个字段?

问题描述

我正在用猫鼬编写一个复杂的聚合管道。我需要总结我的作者的每篇文章的观点,然后给作者赋予这个价值。数据现在看起来像这样:

{
  _id: "...",
  authorName: "...",
  artiles: [
    {articleTitle: "...", views: 4},
    {articleTitle: "...", views: 2},
    {articleTitle: "...", views: 10},
  ]
}

我想要的数据是这样的:

{
  _id: "...",
  authorName: "...",
  artiles: [
    {articleTitle: "...", views: 4},
    {articleTitle: "...", views: 2},
    {articleTitle: "...", views: 10},
  ],
  totalArticleViews: 16   // 4 + 2 + 10
}

我如何使用猫鼬聚合管道来做到这一点?

另一件事是文章和视图有自己独立的模型。所以在管道中发生的是我正在使用 $lookup 来获取作者的所有文章,并且在 $lookup 内部还有另一个 $pipeline 获取特定文章的所有视图。

Author.aggregate([
  {
    $lookup: {
      from: 'articles',
      as: 'articles',
      let: { localFieldValue: "$_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$author", "$$localFieldValue"] } } },
        { $lookup: { from: 'views', localField: '_id', foreignField: 'document', as: 'views' } },
      ]
    }
  }
])

因此,与其在填充文章和视图之后计算视图计数,不如从包含视图的 $lookup 的 $pipeline 中增加作者的 totalViewCount 会更好。

标签: node.jsmongodbexpressmongoose

解决方案


使用$reduce你可以很容易地做到这一点。

测试代码在这里

询问

  • 减少文章数组,从sum=0查找总浏览量开始
  • 使用该总和在文档中添加一个字段
db.collection.aggregate([
  {
    "$set": {
      "totalArticleViews": {
        "$reduce": {
          "input": "$articles",
          "initialValue": 0,
          "in": {
            "$let": {
              "vars": {
                "tviews": "$$value",
                "article": "$$this"
              },
              "in": {
                "$add": [
                  "$$tviews",
                  "$$article.views"
                ]
              }
            }
          }
        }
      }
    }
  }
])

推荐阅读