如何在子文档中仅投影数组中特定项目的字段?
考虑以下(简化)示例:
{
"_id" : ObjectId("573d70df080cc2cbe8bf3222"),
"name" : "Nissan",
"models" : [
{
"name" : "Altima",
"body" : {
"type" : 2,
"maxprice" : 31800.00,
"minprice" : 21500.00
}
},
{
"name" : "Maxima",
"body" : {
"type" : 2,
"maxprice" : 39200.00,
"minprice" : 28800.00
}
}
]
},
{
"_id" : ObjectId("80cc2cbe8bf3222573d70df0"),
"name" : "Honda",
"models" : [
{
"name" : "Accord",
"body" : {
"type" : 2,
"maxprice" : 34100.00,
"minprice" : 20400.00
}
},
{
"name" : "Civic",
"body" : {
"type" : 3,
"maxprice" : 27900.00,
"minprice" : 19800.00
}
}
]
}
汇总后,我想获得以下输出:
{
"_id" : ObjectId("573d70df080cc2cbe8bf3222"),
"name" : "Nissan",
"models" : [
{
"type" : 2,
"minprice" : 21500.00
},
{
"type" : 2,
"minprice" : 28800.00
}
]
},
{
"_id" : ObjectId("80cc2cbe8bf3222573d70df0"),
"name" : "Honda",
"models" : [
{
"type" : 2,
"minprice" : 20400.00
},
{
"type" : 3,
"minprice" : 19800.00
}
]
}
因此它基本上获取所有文档,文档的所有字段,models
数组中的所有项目,但仅models
中的数组项的某些字段。请帮忙。
答案 0 :(得分:6)
db.collection.aggregate([
{ "$project": {
"name": 1,
"models": {
"$map": {
"input": "$models",
"as": "m",
"in": {
"type": "$$m.body.type",
"minprice": "$$m.body.minprice"
}
}
}
}}
])
答案 1 :(得分:-1)
$unwind是你的朋友
首先,您基本上可以过滤所需的(非嵌套)字段。
var projection = {$project:{name:'$name', models:'$models'}};
db.dum.aggregate(projection)
您的模型,您发布文件
var unwindModels = {$unwind:{'$models'}}
db.dum.aggregate(projection, unwindModels)
我们的想法是,您的模型字段发布的每个文档都将在稍后通过_id字段重新分组。
Foreach文档,您只保留所需的(子)字段
var keepSubFields = {$project:{name:'$name', type:'$models.body.type', minprice:'$models.body.minprice'}}
db.dum.aggregate(projection, unwindModels, keepSubFields)
然后将模型重新聚合为数组(感谢跟踪原始记录的每条记录的_id)
var aggregateModels = {$group:{_id:'$_id', name:{$last:'$name'}, models:{$push:{type:'$type', minprice:'$minprice'}}}}
db.dum.aggregate(projection, unwindModels, keepSubFields, aggregateModels)
note1:这里我们可以使用$ last,因为我们的主键不是_id而是< _id,name>。 ($ first也会很好)
note2:我们通过$ type引用类型,因为当您在aggregateModels阶段迭代集合时,您的记录是表单 < _id,name,type,minprice>