[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 的查詢,速度都比較慢了。

發佈了489 篇原創文章 · 獲贊 350 · 訪問量 290萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章