我可以获得与过滤器匹配的子文档的数量吗?
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供您参考。
我有以下文件
[
{
"_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供您参考。