我可以获得与过滤器匹配的子文档的数量吗?

Can I get the count of subdocuments that match a filter?

我有以下文件

    [
      {
        "_id": "624713340a3d2901f2f5a9c0",
        "username": "fotis",
        "exercises": [
          {
            "_id": "624713530a3d2901f2f5a9c3",
            "description": "Sitting",
            "duration": 60,
            "date": "2022-03-24T00:00:00.000Z"
          },
          {
            "_id": "6247136a0a3d2901f2f5a9c6",
            "description": "Coding",
            "duration": 999,
            "date": "2022-03-31T00:00:00.000Z"
          },
          {
            "_id": "624713a00a3d2901f2f5a9ca",
            "description": "Sitting",
            "duration": 999,
            "date": "2022-03-30T00:00:00.000Z"
          }
        ],
        "__v": 3
      }
    ]

我正在尝试通过以下 aggregation 获取返回的练习数(我知道在我的代码中这样做更容易,但我正在尝试了解如何使用 mongodb 查询)

    db.collection.aggregate([
      {
        "$match": {
          "_id": "624713340a3d2901f2f5a9c0"
        }
      },
      {
        "$project": {
          "username": 1,
          "exercises": {
            "$slice": [
              {
                "$filter": {
                  "input": "$exercises",
                  "as": "exercise",
                  "cond": {
                    "$eq": [
                      "$$exercise.description",
                      "Sitting"
                    ]
                  }
                }
              },
              1
            ]
          },
          "count": {
            "$size": "exercises"
          }
        }
      }
    ])

当我尝试使用 "$size": "exercises" 访问 exercises 字段时,出现错误 query failed: (Location17124) Failed to optimize pipeline :: caused by :: The argument to $size must be an array, but was of type: string

但是当我使用 "$size": "$exercises" 访问子文档 exercises 时,我得到了文档中包含的所有子文档的计数。

注意:我知道在这个例子中我使用$slice并且我将限制设置为1,但在我的代码中它是一个变量。

你实际上是在正确的轨道上。你真的不需要 $slice。您可以只使用 $reduce 来执行过滤。您的计数不起作用的原因是过滤和 $size 处于同一阶段。在这种情况下,它将使用 pre-filtered 数组进行计数。您可以通过添加 $addFields 阶段来解决此问题。

db.collection.aggregate([
  {
    "$match": {
      "_id": "624713340a3d2901f2f5a9c0"
    }
  },
  {
    "$project": {
      "username": 1,
      "exercises": {
        "$filter": {
          "input": "$exercises",
          "as": "exercise",
          "cond": {
            "$eq": [
              "$$exercise.description",
              "Sitting"
            ]
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "count": {
        $size: "$exercises"
      }
    }
  }
])

这里是Mongo playground供您参考。