MongoDb 聚合前的总计数

huangapple go评论60阅读模式
英文:

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" }
  }
}

Playground


<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"
      }
    }
  }
])

Mongo Playground

英文:

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([
  ...,
  {
    &quot;$facet&quot;: {
      &quot;result&quot;: [],
      &quot;total-important-count&quot;: [
        {
          $group: {
            _id: null,
            cnt: {
              $sum: &quot;$count.number_of_important_fruits&quot;
            }
          }
        }
      ]
    }
  },
  {
    &quot;$addFields&quot;: {
      &quot;total-count&quot;: {
        $size: &quot;$result&quot;
      },
      &quot;total-important-count&quot;: {
        $first: &quot;$total-important-count.cnt&quot;
      }
    }
  }
])

Mongo Playground

huangapple
  • 本文由 发表于 2023年2月16日 03:10:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75464445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定