MongoDB 按日期和状态双 $group 聚合
MongoDB double $group aggregation by date and status
我有几个文件看起来像这样(减去许多其他不相关的字段):
[{
status: 'open',
createdDate: 2021-06-17T09:02:58.325Z
},
{
status: 'declined',
createdDate: 2021-07-25T09:09:15.851Z
},
{
status: 'declined',
createdDate: 2021-09-22T09:32:14.958Z
},
{
status: 'open',
createdDate: 2021-09-02T09:45:26.584Z
},
{
status: 'referral',
createdDate: 2021-09-05T09:46:02.764Z
}]
对于集合的这个子组,我想汇总下一个结果:
{
"2021-06" : { submitted: 1, referral: 0, declined: 0},
"2021-07" : { submitted: 1, referral: 0, declined: 1},
"2021-08" : { submitted: 0, referral: 0, declined: 0},
"2021-09" : { submitted: 3, referral: 1, declined: 1},
}
已提交的文件总数(打开、推荐和拒绝)。
我尝试以多种方式使用 $group,但没有成功。
有什么建议么?
谢谢!
查询
- 按日期分组,仅包含年份和月份
- 计数 3 个累加器,第一个总是添加,第二个和第三个仅在看到状态打开(第二个)和状态(拒绝)第三个时才添加
- 将根和数组替换为对象,使数据成为键,并将数据作为嵌套文档,就像您预期的输出一样
aggregate(
[{"$group":
{"_id":{"$dateToString":{"date":"$createdDate", "format":"%Y-%m"}},
"submitted":{"$sum":1},
"referral":{"$sum":{"$cond":[{"$eq":["$status", "open"]}, 1, 0]}},
"declined":
{"$sum":{"$cond":[{"$eq":["$status", "declined"]}, 1, 0]}}}},
{"$replaceRoot":
{"newRoot":
{"$arrayToObject":
[[{"k":"$_id",
"v":
{"submitted":"$submitted",
"referral":"$referral",
"declined":"$declined"}}]]}}}])
OP 要求一个解决方案,其中值成为键,例如2021-06: {...
。本着良好数据设计的精神,我可能会建议一个更简单的管道,将日期值保留为一个值:
db.foo.aggregate([
// The SAME as answer above!
{$group: {
"_id":{"$dateToString":{"date":"$createdDate", "format":"%Y-%m"}},
"submitted":{"$sum":1},
"referral":{"$sum":{"$cond":[{"$eq":["$status", "open"]}, 1, 0]}},
"declined":{"$sum":{"$cond":[{"$eq":["$status", "declined"]}, 1, 0]}}
}}
]);
屈服
{ "_id" : "2021-06", "submitted" : 1, "referral" : 1, "declined" : 0 }
{ "_id" : "2021-07", "submitted" : 1, "referral" : 0, "declined" : 1 }
{ "_id" : "2021-09", "submitted" : 3, "referral" : 1, "declined" : 1 }
现在您可以排序、过滤等,而无需通过 $objectToArray
等将键转换为 rvals。如果完全有必要使用比 _id
更具描述性的键名(而不是通过保留 _id
) 造成混淆,然后附加这些阶段:
,{$addFields: {"date":"$_id"}}
,{$unset: "_id"}
我有几个文件看起来像这样(减去许多其他不相关的字段):
[{
status: 'open',
createdDate: 2021-06-17T09:02:58.325Z
},
{
status: 'declined',
createdDate: 2021-07-25T09:09:15.851Z
},
{
status: 'declined',
createdDate: 2021-09-22T09:32:14.958Z
},
{
status: 'open',
createdDate: 2021-09-02T09:45:26.584Z
},
{
status: 'referral',
createdDate: 2021-09-05T09:46:02.764Z
}]
对于集合的这个子组,我想汇总下一个结果:
{
"2021-06" : { submitted: 1, referral: 0, declined: 0},
"2021-07" : { submitted: 1, referral: 0, declined: 1},
"2021-08" : { submitted: 0, referral: 0, declined: 0},
"2021-09" : { submitted: 3, referral: 1, declined: 1},
}
已提交的文件总数(打开、推荐和拒绝)。 我尝试以多种方式使用 $group,但没有成功。 有什么建议么? 谢谢!
查询
- 按日期分组,仅包含年份和月份
- 计数 3 个累加器,第一个总是添加,第二个和第三个仅在看到状态打开(第二个)和状态(拒绝)第三个时才添加
- 将根和数组替换为对象,使数据成为键,并将数据作为嵌套文档,就像您预期的输出一样
aggregate(
[{"$group":
{"_id":{"$dateToString":{"date":"$createdDate", "format":"%Y-%m"}},
"submitted":{"$sum":1},
"referral":{"$sum":{"$cond":[{"$eq":["$status", "open"]}, 1, 0]}},
"declined":
{"$sum":{"$cond":[{"$eq":["$status", "declined"]}, 1, 0]}}}},
{"$replaceRoot":
{"newRoot":
{"$arrayToObject":
[[{"k":"$_id",
"v":
{"submitted":"$submitted",
"referral":"$referral",
"declined":"$declined"}}]]}}}])
OP 要求一个解决方案,其中值成为键,例如2021-06: {...
。本着良好数据设计的精神,我可能会建议一个更简单的管道,将日期值保留为一个值:
db.foo.aggregate([
// The SAME as answer above!
{$group: {
"_id":{"$dateToString":{"date":"$createdDate", "format":"%Y-%m"}},
"submitted":{"$sum":1},
"referral":{"$sum":{"$cond":[{"$eq":["$status", "open"]}, 1, 0]}},
"declined":{"$sum":{"$cond":[{"$eq":["$status", "declined"]}, 1, 0]}}
}}
]);
屈服
{ "_id" : "2021-06", "submitted" : 1, "referral" : 1, "declined" : 0 }
{ "_id" : "2021-07", "submitted" : 1, "referral" : 0, "declined" : 1 }
{ "_id" : "2021-09", "submitted" : 3, "referral" : 1, "declined" : 1 }
现在您可以排序、过滤等,而无需通过 $objectToArray
等将键转换为 rvals。如果完全有必要使用比 _id
更具描述性的键名(而不是通过保留 _id
) 造成混淆,然后附加这些阶段:
,{$addFields: {"date":"$_id"}}
,{$unset: "_id"}