標題比較拗口,下面給一個具體的例子
- 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 的查詢,速度都比較慢了。