node.js - $group by 之后的动态键
问题描述
我有以下收藏
{
"_id" : ObjectId("5b18d14cbc83fd271b6a157c"),
"status" : "pending",
"description" : "You have to complete the challenge...",
}
{
"_id" : ObjectId("5b18d31a27a37696ec8b5773"),
"status" : "completed",
"description" : "completed...",
}
{
"_id" : ObjectId("5b18d31a27a37696ec8b5775"),
"status" : "pending",
"description" : "pending...",
}
{
"_id" : ObjectId("5b18d31a27a37696ec8b5776"),
"status" : "inProgress",
"description" : "inProgress...",
}
我需要分组status
并动态获取所有密钥status
[
{
"completed": [
{
"_id": "5b18d31a27a37696ec8b5773",
"status": "completed",
"description": "completed..."
}
]
},
{
"pending": [
{
"_id": "5b18d14cbc83fd271b6a157c",
"status": "pending",
"description": "You have to complete the challenge..."
},
{
"_id": "5b18d31a27a37696ec8b5775",
"status": "pending",
"description": "pending..."
}
]
},
{
"inProgress": [
{
"_id": "5b18d31a27a37696ec8b5776",
"status": "inProgress",
"description": "inProgress..."
}
]
}
]
解决方案
并不是说我认为这是一个好主意,主要是因为我在这里根本看不到任何“聚合”,因为在“分组”添加到数组之后,您同样$push
可以通过分组键将所有内容放入数组中"status"
,然后转换为键$replaceRoot
with中的文档$arrayToObject
:
db.collection.aggregate([
{ "$group": {
"_id": "$status",
"data": { "$push": "$$ROOT" }
}},
{ "$group": {
"_id": null,
"data": {
"$push": {
"k": "$_id",
"v": "$data"
}
}
}},
{ "$replaceRoot": {
"newRoot": { "$arrayToObject": "$data" }
}}
])
回报:
{
"inProgress" : [
{
"_id" : ObjectId("5b18d31a27a37696ec8b5776"),
"status" : "inProgress",
"description" : "inProgress..."
}
],
"completed" : [
{
"_id" : ObjectId("5b18d31a27a37696ec8b5773"),
"status" : "completed",
"description" : "completed..."
}
],
"pending" : [
{
"_id" : ObjectId("5b18d14cbc83fd271b6a157c"),
"status" : "pending",
"description" : "You have to complete the challenge..."
},
{
"_id" : ObjectId("5b18d31a27a37696ec8b5775"),
"status" : "pending",
"description" : "pending..."
}
]
}
如果您实际上事先“聚合”,那可能没问题,但是在任何实际大小的集合上,所做的只是试图将整个集合强制转换为一个文档,这可能会打破16MB 的 BSON 限制,所以我不推荐甚至在此步骤之前没有“分组”其他东西的情况下尝试这样做。
坦率地说,相同的以下代码做同样的事情,并且没有聚合技巧,也没有 BSON 限制问题:
var obj = {};
// Using forEach as a premise for representing "any" cursor iteration form
db.collection.find().forEach(d => {
if (!obj.hasOwnProperty(d.status))
obj[d.status] = [];
obj[d.status].push(d);
})
printjson(obj);
或者更短一点:
var obj = {};
// Using forEach as a premise for representing "any" cursor iteration form
db.collection.find().forEach(d =>
obj[d.status] = [
...(obj.hasOwnProperty(d.status)) ? obj[d.status] : [],
d
]
)
printjson(obj);
聚合用于“数据减少”,任何只是“重塑结果”而没有实际减少从服务器返回的数据的东西通常最好在客户端代码中处理。无论您做什么,您仍然会返回所有数据,并且游标的客户端处理的开销要少得多。并且没有限制。
推荐阅读
- java - 如何构建两个构建 android 变体以使用 Retrofit 获取两个不同的 URL?
- java - 在 Spring Boot 中使用 application.yml 配置嵌入式 Tomcat 的日志记录
- javascript - 如何使用 java 脚本从函数内部获取值?
- mysql - 如果列不为空,mysql SELECT 并总结
- html - 如何将我的游戏上传到 Facebook Instant Games
- c++ - 有没有办法使用 Johnny-5 发送 C/C++ 命令?
- dialogflow-es - 如何在 Dialogflow 中捕获用户的自由言论?
- python - Python将上下文添加到循环中的日志记录
- r - 更改堆叠 Geom_Bar 的顺序
- ruby-on-rails-5 - ruby gem audited 不记录 created_at 和 updated_at