Mongodb 聚合行到列

Mongodb Aggregation Rows to Columns

我有以下数据集。我需要按帐户对它们进行分组,然后将 Element_Fieldname 变成一列。

var collection = [
    {
        Account:12345,
        Element_Fieldname:"cars",
        Element_Value:true
    },
    {
        Account:12345,
        Element_Fieldname:"boats",
        Element_Value:false
    }
]

这是我尝试将行转换为列的尝试,但它不起作用。

db.getCollection('my_collection').aggregate([{
            $match : {
                Element_Fieldname : {
                    $in : ["cars", "boats"]
                }
            }
        }, {
            $group : {
                _id : "$Account",
                values : {
                    $addToSet : {
                        field : "$Element_Fieldname",
                        value : "$Element_Value"
                    }
                }
            }
        }, {
            $project : {
                Account : "$_id",
                cars : {
                    "$cond" : [{
                            $eq : ["$Element_Fieldname", "cars"]
                        }, "$Element_Value", null]
                },
                boats : {
                    "$cond" : [{
                            $eq : ["$Element_Fieldname", "day_before_water_bottles"]
                        }, "$Element_Value", null]
                },
            }
        }
    ])

这只是在我的 carsboats 字段中给了我 null。任何帮助都会很棒。

这是我想要的结果:

var desiredResult = [
    {
        Account:12345,
        cars:true,
        boats:false
    }
]

这是一个很大的技巧,但你会得到你需要的:-)

请在聚合管道顶部添加 $match

db.collection.aggregate([{
            $project : {
                _id : 0,
                "Account" : 1,
                car : {
                    $cond : [{
                            $eq : ["$Element_Fieldname", "cars"]
                        }, "$Element_Value", null]
                },
                boats : {
                    $cond : [{
                            $eq : ["$Element_Fieldname", "boats"]
                        }, "$Element_Value", null]
                },
            }
        },
        {
            $group : {
                _id : "$Account",
                carData : {
                    $addToSet : "$car"
                },
                boatsData : {
                    $addToSet : "$boats"
                }
            }
        }, {
            $unwind : "$carData"
        }, {
            $match : {
                carData : {
                    $ne : null
                }
            }
        }, {
            $unwind : "$boatsData"
        }, {
            $match : {
                boatsData : {
                    $ne : null
                }
            }
        },
    ])

和结果

{
    "_id" : 12345,
    "carData" : true,
    "boatsData" : false
}

无法使用聚合框架进行您描述的计算类型,但是有一个建议的 $arrayToObject 表达式可以为您提供功能查看键名,并动态创建新的 key/values。

例如,您可以这样做

db.collection.aggregate([
    {
        "$match": { "Element_Fieldname":{ "$in": ["cars", "boats"] } }
    },    
    {
        "$group": {
            "_id": "$Account",
            "attrs": { 
                "$push": {
                    "key": "$Element_Fieldname",
                    "val": "$Element_Value"
                } 
            }            
        }
    },
    {
        "$project": {
            "Account": "$_id",
            "_id": 0,
            "newAttrs": {
                "$arrayToObject": {
                    "$map": {
                        "input": "$attrs",
                        "as": "el",
                        in: ["$$el.key", "$$el.val"]
                    }
                }
            }
        }
    },
    {
        "$project": {
            "Account": 1,
            "cars": "$newAttrs.cars",
            "boats": "$newAttrs.boats"
        }
    }
])

为这张 jira 票https://jira.mongodb.org/browse/SERVER-23310投票以获得此功能。


作为解决方法,mapreduce 似乎是可用的选项。考虑 运行 以下 map-reduce 操作:

db.collection.mapReduce(
    function() {
        var obj = {};
        obj[this.Element_Fieldname] = this.Element_Value;        
        emit(this.Account, obj);
    },
    function(key, values) {
        var obj = {};
        values.forEach(function(value) {
            Object.keys(value).forEach(function(key) {                
                obj[key] = value[key];
            });
        });
        return obj;
    },
    { "out": { "inline": 1 } }
)

结果:

{
    "_id" : 12345,
    "value" : {
        "cars" : true,
        "boats" : false
    }
}