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

10

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

考虑以下(简化)示例:

{
    "_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个回答

16

您需要使用$map操作符对"models"字段进行$project投影处理。

db.collection.aggregate([ 
    { "$project": { 
        "name": 1, 
        "models": { 
            "$map": { 
                "input": "$models", 
                "as": "m", 
                "in": { 
                    "type": "$$m.body.type", 
                    "minprice": "$$m.body.minprice" 
                } 
            } 
        }  
    }} 
])

这太棒了! - Alex
我不得不从"type": "$$m.body.type"中删除".body"才能使其正常工作。(如果有人遇到同样的问题) - K P

-1

$unwind 是你的好朋友

首先,你可以基本过滤掉你想要的(非嵌套)字段。

var projection = {$project:{name:'$name', models:'$models'}};
db.dum.aggregate(projection)

对于您的每个模型,您都会发布一个文档

var unwindModels = {$unwind:{'$models'}}
db.dum.aggregate(projection, unwindModels)

这个想法是,从您的模型字段发出的每个文档都将通过 _id 字段稍后进行重新分组。

对于每个文档,您只保留所需的(子)字段。

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)

注意1:在这里我们可以使用$last,因为我们的主键不是_id,而是<_id,name>。 ($first也可以)

注意2:我们通过$type来引用类型,因为当您在aggregateModels阶段迭代集合时,您的记录形式为<_id,name,type,minprice>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接