MongoDB 聚合:将单独的文档字段投影到单个数组字段中

MongoDB aggregation: Project separate document fields into a single array field

我有这样一个文档:

{fax: '8135551234', cellphone: '8134441234'}

有没有办法将这份文件(没有小组赛阶段)投射到:

{
    phones: [{
        type: 'fax',
        number: '8135551234'
    }, {
        type: 'cellphone',
        number: '8134441234'
    }]
}

我可能会为此使用小组阶段运算符,但如果有任何其他方法我宁愿不这样做,因为我的查询还投影了其他几个字段,所有这些都需要 $first 只是为了小组赛。

希望这很清楚。提前致谢!

MongoDB 2.6 引入了 $map 运算符,它是一个数组转换运算符,可用于执行此操作:

db.phones.aggregate([
    { "$project": {
        "phones": { "$map": {
            "input": { "$literal": ["fax","cellphone"] },
            "as": "el",
            "in": {
                "type": "$$el",
                "number": { "$cond": [
                     { "$eq": [ "$$el", "fax" ] },
                     "$fax",
                     "$cellphone"
                 ]}
             }
        }}
    }}
])

所以您的文档现在看起来与您想要的完全一样。诀窍当然是创建一个包含成员 "fax" 和 "cellphone" 的新数组,然后通过匹配这些值用新文档字段转换该数组。

当然,您也可以在早期版本中以类似的方式使用 $unwind and $group 执行此操作,但效率不高:

db.phones.aggregate([
    { "$project": {
        "type": { "$const": ["fax","cellphone"] },
        "fax": 1,
        "cellphone": 1
    }},
    { "$unwind": "$type" },
    { "$group": {
        "_id": "_id",
        "phones": { "$push": { 
            "type": "$type",
            "number": { "$cond": [
                { "$eq": [ "$type", "fax" ] },
                "$fax",
                "$cellphone"
            ]}
        }}
    }}
])

当然可以说,除非您正在进行某种聚合,否则您也可以 post 在代码中处理收集结果。但这是另一种方法。