use*_*515 8 mongodb mongodb-query aggregation-framework
在聚合分组期间,我遇到了重塑文档的问题.基本上我想根据类型将条目推送到字段.我的结构如下:
_id: P1
entities: [{type: A, val: X}, {type: B, val: X}, {type: A, val: Y}]
...
Run Code Online (Sandbox Code Playgroud)
我想$ unwind和$投影这些实体,以便获得如下结构:
_id: P1
A: [X]
B: []
_id: P1
A: [Y]
B: []
_id: P1
A: []
B: [X]
Run Code Online (Sandbox Code Playgroud)
所以我可以通过A或B或两者进行分组,即
$group: {
_id: {
A: $A,
B: $B
}
count: {$sum : 1}
Run Code Online (Sandbox Code Playgroud)
我以为我可以做到:
$unwind: $entities
$project: {
id: §id
A: {"$cond":[{"$eq":["$type","A"]},"$code"]}
B: {"$cond":[{"$eq":["$type","B"]},"$code"]}
}
$group: {
_id: "$id"
A: {$addToSet : "$A"}
}
Run Code Online (Sandbox Code Playgroud)
或失败的东西
$unwind: $entities
$group: {
_id: "$id"
A: {"$cond":[{"$eq":["$type","A"]},$push: "$code", null]}
...
}
Run Code Online (Sandbox Code Playgroud)
但是这两个版本都失败了,因为我对其他内容无能为力,而且我没有设法在条件内使用$ push.我得到的最接近的是项目取决于类型,但由于我找不到在没有匹配时不向场添加任何内容的方法,我最终得到:
_id: P1
A: [X,null,Y]
B: [null,X,null]
Run Code Online (Sandbox Code Playgroud)
这弄乱了计数.我的第二个想法是过滤数组以删除null.但我没有找到删除实体的方法,因为再次$ cond不会让我指定一个空/"什么都不做"的情况.
我觉得它可以通过类型和内容进行分组以及所需类型的匹配,但由于我有许多类型和任意分组导致分组树,这可能会变得非常复杂.对错误的想法或提示将非常受欢迎.
谢谢
编辑:基于接受的anwser的解决方案
我不得不稍微调整它,以过滤一个类型的所有内容都为null的情况,因为否则它会在匹配期间丢失,因为我想保留这些知识.谢谢!
{$project:{
A: {$cond: [
{$eq: ["$A", [false]]},
["N/A"],
"$A"
]},
B: {$cond: [
{$eq: ["$B", [false]]},
["N/A"],
"$B"
]},
}},
{ "$unwind": "$A" },
{ "$match": { "A": { "$ne": false } } },
{ "$group": {
"_id": "$_id",
"A": { "$push": "$A" },
"B": { "$first": "$B" }
}},
{ "$unwind": "$B" },
{ "$match": { "B": { "$ne": false } } },
{ "$group": {
"_id": "$_id",
"A": { "$first": "$A" },
"B": { "$push": "$B" }
}}
Run Code Online (Sandbox Code Playgroud)
Nei*_*unn 14
您似乎走在正确的轨道上,只有不同的方法可以false从条件中删除这些值.你不能让它什么都不返回,但你可以摆脱你不想要的值.
如果你真的想要"套装"并且你有MongoDB 2.6或更高版本,那么你基本上可以false使用$setDifference以下方法过滤掉这些值:
db.entities.aggregate([
{ "$unwind": "$entities" },
{ "$group": {
"_id": "$_id",
"A": {
"$addToSet": {
"$cond": [
{ "$eq": [ "$entities.type", "A" ] },
"$entities.val",
false
]
}
},
"B": {
"$addToSet": {
"$cond": [
{ "$eq": [ "$entities.type", "B" ] },
"$entities.val",
false
]
}
}
}},
{ "$project": {
"A": {
"$setDifference": [ "$A", [false] ]
},
"B": {
"$setDifference": [ "$B", [false] ]
}
}}
])
Run Code Online (Sandbox Code Playgroud)
db.entities.aggregate([
{"$project": {
"A": {
"$setDifference": [
{
"$map": {
"input": "$entities",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.type", "A" ] },
"$$el.val",
false
]
}
}
},
[false]
]
},
"B": {
"$setDifference": [
{
"$map": {
"input": "$entities",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.type", "B" ] },
"$$el.val",
false
]
}
}
},
[false]
]
}
}}
])
Run Code Online (Sandbox Code Playgroud)
或以其他方式与一般$unwind和$match运营商一起过滤这些:
db.entities.aggregate([
{ "$unwind": "$entities" },
{ "$group": {
"_id": "$_id",
"A": {
"$push": {
"$cond": [
{ "$eq": [ "$entities.type", "A" ] },
"$entities.val",
false
]
}
},
"B": {
"$push": {
"$cond": [
{ "$eq": [ "$entities.type", "B" ] },
"$entities.val",
false
]
}
}
}},
{ "$unwind": "$A" },
{ "$match": { "A": { "$ne": false } } },
{ "$group": {
"_id": "$_id",
"A": { "$push": "$A" },
"B": { "$first": "$B" }
}},
{ "$unwind": "$B" },
{ "$match": { "B": { "$ne": false } } },
{ "$group": {
"_id": "$_id",
"A": { "$first": "$A" },
"B": { "$push": "$B" }
}}
])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5582 次 |
| 最近记录: |