[MongoDB] 聚合嵌入 object 的 key

标题比较拗口,下面给一个具体的例子

  • MongoDB 3.6

数据样本

{
    "_id" : ObjectId("5a79391534cdbd692825e978"),
    "cdn" : "Conversant",
    "domain" : "7img1.xxxx.com",
    "status_code" : {
        "200" : 80,
        "206" : 3,
        "404" : 2,
        "304" : 4
    }
}

status_code 字段就是标题中提到的 嵌入object, 需求是 统计某一段时间内,记录中 所有状态码 的聚合,麻烦就在所有状态码的集合。

情况一

如果状态码是可以枚举的,是个有限的集合 {200, 201, 206, 301, 404.. 504} 比较好办, 用下面的方式就可以解决。

db.getCollection('log_coll').aggregate(
    {"$match": {"time": {"$gte": 1517900400, "$lt": 1517986800}}},
    {"$group": {
        "_id": null,
        "000": {"$sum": "$status_code.000"},
        "200": {"$sum": "$status_code.200"},
        "206": {"$sum": "$status_code.206"},
        "302": {"$sum": "$status_code.302"},
        "301": {"$sum": "$status_code.301"},
        "305": {"$sum": "$status_code.305"},
        "403": {"$sum": "$status_code.403"},
        "404": {"$sum": "$status_code.404"},
        "415": {"$sum": "$status_code.415"},
        "416": {"$sum": "$status_code.416"},
        "503": {"$sum": "$status_code.503"},
        "502": {"$sum": "$status_code.502"},
        "504": {"$sum": "$status_code.504"},
        "500": {"$sum": "$status_code.500"},
        "-": {"$sum": "$status_code.-"}
    }}
);

情况二

如果 status_code 中的 key 范围无法确定,只能用 mapreduce 的方式来查询了。

db.getCollection('log_coll').mapReduce(
    function(){
        var codes = this.status_code;
        Object.keys(codes).forEach(function(k){
            emit(k, codes[k]);
        })
    },
    function(k, v){
        return Array.sum(v);
    },
    { 
      out : {inline : 1},
      query: {"time": {"$gte": 1517900400, "$lt": 1517986800}} 
    }
)

上面两种方式属于 OLAP 的查询,速度都比较慢了。

猜你喜欢

转载自blog.csdn.net/lzz957748332/article/details/79870378