gpt4 book ai didi

mongodb - 聚合以从值创建动态键

转载 作者:可可西里 更新时间:2023-11-01 09:48:19 26 4
gpt4 key购买 nike

我有一个聚合表达式如下:

db.Booking.aggregate([
{ $match: { created_at: {$exists:true} } },
{ $sort : { created_at : -1 } },
{ $group: {
_id: {
year : { $year : "$created_at" },
month : { $month : "$created_at" },
accepted: '$accepted'
},
total: {
$sum: '$total'
}
}
}
])

生成的结果如下:

[
{"_id":{"year":2017,"month":4,"accepted":"expired"},"total":0},
{"_id":{"year":2017,"month":4,"accepted":"Expired"},"total":25},
{"_id":{"year":2017,"month":4,"accepted":"Pending"},"total":390},
{"_id":{"year":2017,"month":5,"accepted":"Pending"},"total":1400}
]

我如何得到这样的结果:

[
{"_id":{"year":2017,"month":4},"expired":0},
{"_id":{"year":2017,"month":4},"Expired":25},
{"_id":{"year":2017,"month":4},"Pending":390},
{"_id":{"year":2017,"month":5},"Pending":1400}
]

我是否必须使用常规 javascript 进行修改而不是依赖 Mongodb 来完成这项工作

最佳答案

您确实“应该”处理结果以在您的接收代码中命名这些键,而不是依赖数据库来执行此操作。虽然最新的当前版本可能需要一些争论。

这至少需要 MongoDB 3.4:

db.Booking.aggregate([
{ "$match": { "created_at": { "$exists": true } } },
{ "$sort": { "created_at": -1 } },
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"month": { "$month": "$created_at" },
"accepted": {
"$concat": [
{ "$toUpper": { "$substrCP": [ "$accepted", 0, 1 ] } },
{ "$toLower": { "$substrCP": [ "$accepted", 1, { "$strLenCP": "$accepted" } ] } }
]
}
},
"total": { "$sum": "$total" }
}},
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$concatArrays": [
[
{ "k": "_id", "v": { "year": "$_id.year", "month": "$_id.month" } },
{ "k": "$_id.accepted", "v": "$total" }
]
]
}
}
}}
])

其中大部分由 $arrayToObject$replaceRoot 处理流水线阶段。可能会注意到 $concatArrays这里的用法似乎是必要的,因为如果简单地提供数组文字作为参数,$arrayToObject 会报错。所以我们使用一个运算符,它从它自己的给定表达式返回一个数组,并且 $concatArrays似乎是最简短的符号。

这似乎是一个错误(有待确认),但很可能只是作为预期用途,因为对于大多数聚合运算符,数组 [] 参数通常用于多个参数。

此外,您的一般 $group 似乎也有问题语句,因为 "accepted" 值的大小写不同,MongoDB 将对其进行不同的处理。您可以使用 $toLower 等运算符来纠正此问题和 $toUpper .在这里,我使用一些现代运算符来使首字母一致为大写,其余字母为小写,但基本大小写函数在所有支持 .aggregate() 的版本中都可用。

当然,后期处理非常简单,任何版本都可以完成。对于来自 MongoDB shell 的 JavaScript,它非常简单,如下所示:

db.Booking.aggregate([
{ "$match": { "created_at": { "$exists": true } } },
{ "$sort": { "created_at": -1 } },
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"month": { "$month": "$created_at" },
"accepted": {
"$concat": [
{ "$toUpper": { "$substrCP": [ "$accepted", 0, 1 ] } },
{ "$toLower": { "$substrCP": [ "$accepted", 1, { "$strLenCP": "$accepted" } ] } }
]
}
},
"total": { "$sum": "$total" }
}}
]).forEach(doc => {
doc[doc._id.accepted] = doc.total;
delete doc._id.accepted;
delete doc.total;
printjson(doc)
})

两者产生相同的东西:

{ "_id" : { "year" : 2017, "month" : 4 }, "Expired" : 25 }
{ "_id" : { "year" : 2017, "month" : 4 }, "Pending" : 390 }
{ "_id" : { "year" : 2017, "month" : 5 }, "Pending" : 1400 }

如果您实际上想要在分组结果中“同时”使用“Pending”和“Expired”键,那就更简单了:

db.Booking.aggregate([
{ "$match": { "created_at": { "$exists": true } } },
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"month": { "$month": "$created_at" }
},
"Expired": {
"$sum": {
"$cond": [
{ "$eq": [ { "$toLower": "$accepted" }, "expired" ] },
"$total",
0
]
}
},
"Pending": {
"$sum": {
"$cond": [
{ "$eq": [ { "$toLower": "$accepted" }, "pending" ] },
"$total",
0
]
}
}
}},
{ "$sort": { "_id": 1 } }
])

哪个返回:

{ "_id" : { "year" : 2017, "month" : 4 }, "Expired" : 25, "Pending" : 390 }
{ "_id" : { "year" : 2017, "month" : 5 }, "Expired" : 0, "Pending" : 1400 }

由于文档中的键有一个“固定”格式,它们不会变化,所以这是一个简单的布局,我们只使用 $cond使用 $sum 决定在每个键下累积哪些值.

关于mongodb - 聚合以从值创建动态键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44479875/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com