执行 $group 并计数 mongoDB 聚合
Perform $group and count in mongoDB aggregation
鉴于我有一个复杂的分组要求,我想知道实现我想要的结果的最佳方法是什么。
我的数据($project 阶段的结果)看起来像这样:
{
_id:$id
status:"available"
inspectionStatus:"done"
state:"completed"
category:"One"
},
{
_id:$id
status:"booked"
inspectionStatus:"none"
state:"active"
category:"Two"
},
.
.
.
我尝试使用 $facet
创建多个存储桶,因为我尝试创建的分组是 $status
+ $state
+ $inspection
的聚合,但是执行时间是无法接受的,大约需要 1639763842
毫秒。
我不能使用 use $accumulator
因为 mongoDB 版本(虽然我们总是可以升级到 4.4.x)但是我不确定使用 $accumulator
是否会产生更好的效果响应时间。
$facet
阶段包括:
{
"available": [
{"$match":
{$and: [
{"status": "available"},
{"inspectionStatus": "done"}
]}
}
],
"matched": [
{"$match":
{$and: [
{"status": "booked"},
{"state": "booked"}
]
}
}
],
"inIntake": [
{"$match":
{$and: [
{"status": "available"},
{"inspectionStatus": {$ne: "done"}}
]
}
}
],
"active": [
{"$match":
{$and: [
{"status": "booked"},
{"state": "active"}
]
}
}
],
"unreturned":[
{"$match":
{"status": "forceCompleted"}
}
]
}
如果您真的想将逻辑推送到数据库,这里有一个解决方案——但您仍然需要按文档检查 XX
字段文档:
db.foo.aggregate([
{$addFields: {XX: {$switch: {
branches: [
{ case: {
$and: [{$eq:["$status","available"]},{$eq:["$inspectionStatus","done"]}]
}, then:'AVAILABLE' },
{ case: {
$and: [{$eq:["$status","booked"]},{$eq:["$state","booked"]}]
}, then:'MATCHED' },
{ case: {
$and: [{$eq:["$status","available"]},{$ne:["$inspectionStatus","done"]}]
}, then:'IN_INTAKE' },
{ case: {
$and: [{$eq:["$status","booked"]},{$eq:["$state","active"]}]
}, then:'ACTIVE' },
{ case: {
$eq:["$status","forceCompleted"]
}, then:'UNRETURNED' },
],
default: null
}}
}}
,{$match: {XX: {$ne: null}}}
]);
这方面的端到端计时实际上比简单的 find()
好几毫秒,因为传输的 material 较少,但当然数据库引擎正在更努力地处理管道。
鉴于我有一个复杂的分组要求,我想知道实现我想要的结果的最佳方法是什么。 我的数据($project 阶段的结果)看起来像这样:
{
_id:$id
status:"available"
inspectionStatus:"done"
state:"completed"
category:"One"
},
{
_id:$id
status:"booked"
inspectionStatus:"none"
state:"active"
category:"Two"
},
.
.
.
我尝试使用 $facet
创建多个存储桶,因为我尝试创建的分组是 $status
+ $state
+ $inspection
的聚合,但是执行时间是无法接受的,大约需要 1639763842
毫秒。
我不能使用 use $accumulator
因为 mongoDB 版本(虽然我们总是可以升级到 4.4.x)但是我不确定使用 $accumulator
是否会产生更好的效果响应时间。
$facet
阶段包括:
{
"available": [
{"$match":
{$and: [
{"status": "available"},
{"inspectionStatus": "done"}
]}
}
],
"matched": [
{"$match":
{$and: [
{"status": "booked"},
{"state": "booked"}
]
}
}
],
"inIntake": [
{"$match":
{$and: [
{"status": "available"},
{"inspectionStatus": {$ne: "done"}}
]
}
}
],
"active": [
{"$match":
{$and: [
{"status": "booked"},
{"state": "active"}
]
}
}
],
"unreturned":[
{"$match":
{"status": "forceCompleted"}
}
]
}
如果您真的想将逻辑推送到数据库,这里有一个解决方案——但您仍然需要按文档检查 XX
字段文档:
db.foo.aggregate([
{$addFields: {XX: {$switch: {
branches: [
{ case: {
$and: [{$eq:["$status","available"]},{$eq:["$inspectionStatus","done"]}]
}, then:'AVAILABLE' },
{ case: {
$and: [{$eq:["$status","booked"]},{$eq:["$state","booked"]}]
}, then:'MATCHED' },
{ case: {
$and: [{$eq:["$status","available"]},{$ne:["$inspectionStatus","done"]}]
}, then:'IN_INTAKE' },
{ case: {
$and: [{$eq:["$status","booked"]},{$eq:["$state","active"]}]
}, then:'ACTIVE' },
{ case: {
$eq:["$status","forceCompleted"]
}, then:'UNRETURNED' },
],
default: null
}}
}}
,{$match: {XX: {$ne: null}}}
]);
这方面的端到端计时实际上比简单的 find()
好几毫秒,因为传输的 material 较少,但当然数据库引擎正在更努力地处理管道。