【问题标题】:Project only some fields of array items in sub document仅投影子文档中数组项的某些字段
【发布时间】:2016-11-24 21:32:29
【问题描述】:

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

考虑以下(简化的)示例:

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

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

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

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

    【讨论】:

    • 这太棒了!
    • 我必须从 "type": "$$m.body.type" 中删除 ".body" 才能正常工作。 (如果有人遇到同样的问题)
    【解决方案2】:

    $unwind是你的朋友

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

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

    Foreach 你的模型,你发布一个文件

    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)
    

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

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

    【讨论】:

      猜你喜欢
      • 2014-06-08
      • 1970-01-01
      • 2019-07-12
      • 2014-01-06
      • 1970-01-01
      • 2016-02-23
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      相关资源
      最近更新 更多