仅在子文档中投影数组项的某些字段

时间:2016-11-24 21:32:29

标签: mongodb aggregation-framework

如何在子文档中仅投影数组中特定项目的字段?

考虑以下(简化)示例:

{
    "_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中的数组项的某些字段。请帮忙。

2 个答案:

答案 0 :(得分:6)

您需要使用$project运算符$map“模型”字段。

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>