英文:
MongoDb Aggregate Total Count Before Grouping
问题
我有一个聚合管道,用于分组对象并在分组对象的特定字段上保存计数。您可以在此处重现问题:https://mongoplayground.net/p/2DGaiQDYDBP。
模式如下:
[
  {
    "_id": {
      "$oid": "63ce93ffb6e06322db59fdc0"
    },
    "fruit": "apple",
    "source": "tree",
    "is_fruit_important": "true"
  },
  {
    "_id": {
      "$oid": "63ce93ffb6e06322db59fdc1"
    },
    "fruit": "orange",
    "source": "tree",
    "is_fruit_important": "false"
  }
]
当前查询按源分组水果,并保存每个组的重要水果计数。应用聚合后,查询结果类似于以下内容:
[
  {
    "count": {
      "number_of_important_fruits": 1
    },
    "objects": [
      {
        "fruit": "apple",
        "id": "63ce93ffb6e06322db59fdc0",
        "is_fruit_important": "true",
        "source": "tree"
      },
      {
        "fruit": "orange",
        "id": "63ce93ffb6e06322db59fdc1",
        "is_fruit_important": "false",
        "source": "tree"
      }
    ],
    "source": {
      "source-of": "tree"
    }
  }
]
是否有一种方法可以将数据库中的所有水果数量添加到响应对象中?例如,像这样:
{
  "total-count": 2,
  "result": [
    {
      "count": {
        "number_of_important_fruits": 1
      },
      "objects": [
        {
          "fruit": "apple",
          "id": "63ce93ffb6e06322db59fdc0",
          "is_fruit_important": "true",
          "source": "tree"
        },
        {
          "fruit": "orange",
          "id": "63ce93ffb6e06322db59fdc1",
          "is_fruit_important": "false",
          "source": "tree"
        }
      ],
      "source": {
        "source-of": "tree"
      }
    }
  ]
}
它们可以在单独的聚合管道中处理,但我不想实现这种方式。任何帮助将不胜感激。
英文:
I have an aggregation pipeline that groups objects and holds count for some specific field for grouped objects. You can reproduce the problem here: https://mongoplayground.net/p/2DGaiQDYDBP .
The schema is like this;
[
  {
    "_id": {
      "$oid": "63ce93ffb6e06322db59fdc0"
    },
    "fruit": "apple",
    "source": "tree",
    "is_fruit_important": "true"
  },
  {
    "_id": {
      "$oid": "63ce93ffb6e06322db59fdc1"
    },
    "fruit": "orange",
    "source": "tree",
    "is_fruit_important": "false"
  },
]
and the current query groups fruits by the source, and holds the count of important fruits for every group. After applying aggregation I get something like this after query:
[
  {
    "count": {
      "number_of_important_fruits": 1
    },
    "objects": [
      {
        "fruit": "apple",
        "id": "63ce93ffb6e06322db59fdc0",
        "is_fruit_important": "true",
        "source": "tree"
      },
      {
        "fruit": "orange",
        "id": "63ce93ffb6e06322db59fdc1",
        "is_fruit_important": "false",
        "source": "tree"
      }
    ],
    "source": {
      "source-of": "tree"
    }
  }
]
Is there a way to put the number of all fruits in the database to the response object. For example like this:
  {
    "total-count": 2,
    "result": [
      {
        "count": {
          "number_of_important_fruits": 1
        },
        "objects": [
          {
            "fruit": "apple",
            "id": "63ce93ffb6e06322db59fdc0",
            "is_fruit_important": "true",
            "source": "tree"
          },
          {
            "fruit": "orange",
            "id": "63ce93ffb6e06322db59fdc1",
            "is_fruit_important": "false",
            "source": "tree"
          }
        ],
        "source": {
          "source-of": "tree"
        }
      }
    ]
  }
They can be handled in separate aggregation pipelines but that's what I would not like to implement. Any help would be highly appreciated.
答案1
得分: 2
{
  "$group": {
    "_id": null,
    "result": { "$push": "$$ROOT" },
    "count_total": { "$sum": { "$size": "$objects" } },
    "count_important": { "$sum": "$count.number_of_important_fruits" }
  }
}
<details>
<summary>英文:</summary>
Add one additional group stage just before the final $project, using `$sum` with `$size` for a total count, or add up the important counts for a total important count.
{$group: {
_id: null,
result: {$push: "$$ROOT"},
"count_total": {$sum: {$size: "$objects"}},
"count_important": {$sum: "$count.number_of_important_fruits"}
}},
[Playground](https://mongoplayground.net/p/mocYDXQjHCF)
</details>
# 答案2
**得分**: 1
你只需在聚合管道中添加一个`$facet`阶段,将所有结果推送到`result`中。然后对`result`执行`$size`操作以获取`total-count`。
```js
db.collection.aggregate([
  ...,
  {
    "$facet": {
      "result": [],
      "total-important-count": [
        {
          $group: {
            _id: null,
            cnt: {
              $sum: "$count.number_of_important_fruits"
            }
          }
        }
      ]
    }
  },
  {
    "$addFields": {
      "total-count": {
        $size: "$result"
      },
      "total-important-count": {
        $first: "$total-important-count.cnt"
      }
    }
  }
])
英文:
You can simply add a $facet stage to push all your results into result. Then perform a $size on result to get total-count.
db.collection.aggregate([
  ...,
  {
    "$facet": {
      "result": [],
      "total-important-count": [
        {
          $group: {
            _id: null,
            cnt: {
              $sum: "$count.number_of_important_fruits"
            }
          }
        }
      ]
    }
  },
  {
    "$addFields": {
      "total-count": {
        $size: "$result"
      },
      "total-important-count": {
        $first: "$total-important-count.cnt"
      }
    }
  }
])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论