标题比较拗口,下面给一个具体的例子
- 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 的查询,速度都比较慢了。