MongoDB聚合:如何根据条件获得列数

MongoDB聚合:如何根据条件获得列数,mongodb,Mongodb,我有以下文件: { "col1": "camera", "fps": 1, "lat": 3 }, { "col1": "camera", "fps": 3, "lat": 2 } { "col1": "camera", "foo": 9, "bar": 7 } { "col1": "camera", "bar": 8, "bar": 1 } { "col1": "camera", "check": 4, "lat": 3 } 我如何获得以下信息: { "fps": 2, "lat": 3,

我有以下文件:

{ "col1": "camera", "fps": 1, "lat": 3 },
{ "col1": "camera", "fps": 3, "lat": 2 }
{ "col1": "camera", "foo": 9, "bar": 7 }
{ "col1": "camera", "bar": 8, "bar": 1 }
{ "col1": "camera", "check": 4, "lat": 3 }
我如何获得以下信息:

{ "fps": 2, "lat": 3, "bar": 3, "check": 1, "foo": 1 }

其中,这些值中的每一个都是每个键的出现次数(计数)(fps出现2次、foo出现一次等)

聚合

这里有一个解决方案(我将我的收藏命名为“摄影机”),前提是事先知道关键点:

 db.cameras.aggregate([
{
    $project: {
        _id: 1,
        fps: {
            $ifNull: [ "$fps", 0 ]
        },
        lat: {
            $ifNull: [ "$lat", 0 ]
        },
        bar: {
            $ifNull: [ "$bar", 0 ]
        },
        foo: {
            $ifNull: [ "$foo", 0 ]
        },
        check: {
            $ifNull: [ "$check", 0 ]
        }
    }
},
{
    $project: {
        _id: 1,
        fps: {
            $cond: [ { $eq: [ "$fps", 0 ] } , 0, 1 ]
        },
        lat: {
            $cond: [ { $eq: [ "$lat", 0 ] } , 0, 1 ]
        },
        bar: {
            $cond: [ { $eq: [ "$bar", 0 ] } , 0, 1 ]
        },
        foo: {
            $cond: [ { $eq: [ "$foo", 0 ] } , 0, 1 ]
        },
        check: {
            $cond: [ { $eq: [ "$check", 0 ] } , 0, 1 ]
        }
    }
},
{
    $group: {
        _id: null,
        fps: {
            $sum: "$fps"
        },
        lat: {
            $sum: "$lat"
        },
        bar: {
            $sum: "$bar"
        },
        foo: {
            $sum: "$foo"
        },
        check: {
            $sum: "$check"
        }
    }
}
])
结果:

MapReduce

如果密钥未知,另一种解决方案是mapReduce:

db.cameras.mapReduce(
    function() {
        var keys = Object.keys(this);
        keys.forEach(function(key) {
            emit(key, 1);
        });
    },
    function(key, values) {
        return Array.sum(values);
    },
    {
        query: {},
        out: {
            inline: 1
        }
    }
)
结果:


但是结果的格式并不完全相同。

解决方案假定所有可能的键名都是事先已知的。是的,使用mapReduce,在没有已知键的情况下也可以。你有更好的解决办法吗?
db.cameras.mapReduce(
    function() {
        var keys = Object.keys(this);
        keys.forEach(function(key) {
            emit(key, 1);
        });
    },
    function(key, values) {
        return Array.sum(values);
    },
    {
        query: {},
        out: {
            inline: 1
        }
    }
)
{
    "results" : [
        {
            "_id" : "_id",
            "value" : 5
        },
        {
            "_id" : "bar",
            "value" : 2
        },
        {
            "_id" : "check",
            "value" : 1
        },
        {
            "_id" : "col1",
            "value" : 5
        },
        {
            "_id" : "foo",
            "value" : 1
        },
        {
            "_id" : "fps",
            "value" : 2
        },
        {
            "_id" : "lat",
            "value" : 3
        }
    ],
    "timeMillis" : 1,
    "counts" : {
        "input" : 5,
        "emit" : 19,
        "reduce" : 5,
        "output" : 7
    },
    "ok" : 1,
}