MongoDB GroupBy操作, 结果集大小限制问题。

出现问题      

  公司是做互联网广告投放的,需要统计广告展现量在前五百的域名。最简单粗暴的做法就是group by,根据url分组,然后再sort一下就搞定晒!结果问题就出现了。

如下统计的2015-02-28当日22时的日志,文档数量:904405。

db['log.2015-02-28_22'].group({
     key : {domainUrl:1}, 
     initial : {count:0}, 
     reduce : function Reduce(doc, out) {
	out.count++;
}

    报错:

Error in executing GroupBy
Command 'group' failed: exception: group() can't handle more than 20000 unique keys (response: { "errmsg" : "exception: group() can't handle more than 20000 unique keys", "code" : 17203, "ok" : 0.0 })
Type: MongoDB.Driver.MongoCommandException

    错误信息不够具体,加之理解问题,我以为是集合中的文档数量不能超过20000,2万都不能支持那要group干嘛。经过多次测试,终于证明了我是错的。是不支持大于2万的结果集,即分组后产生的文档数量不能超过2万。

//集合大小
> db['log.2015-02-28_22'].count();
904405
//唯一url数量
> db['log.2015-02-28_22'].distinct('domainUrl').length;
20738

这个集合中的唯一url数量是20738,刚好超过了2万,所以MongoDB的group就无能为力了。

另外测试还意外发现,distinct对结果集大小也是有限制的。结果集大小不能超过16Mb。

> db['log.2015-02-28_22'].distinct('webUrl').length;
     distinct failed: {
        "errmsg" : "exception: distinct too big, 16mb cap",
        "code" : 17217,
        "ok" : 0

MongoDB为什么这么多限制,而且阈值都比较小,还请大神指点。

解决问题

    问题是用来解决的,通过stackoverflow大神的指点,我尝试着用MongoDB的mapreduce搞定它,其实一开始我是拒绝的,因为,你不能让我用,我就用;首先,我要看一下我会不会用。结果发现,我不会用,然后看了看MongoDB的说明文档。写出如下代码:

db.runCommand({ mapreduce: "log.2015-02-28_22", 
 map : function Map() {
	emit(
		{   uuid:this.adUUId, //对不同的广告统计url
                    url:this.domainUrl
                },
		{count: 1}	
	); 
 },
 reduce : function Reduce(key, values) {
    var total=0;
	for( var i in values){ 
 		total +=values[i].count;
	} 
 
	return {count:total};	
},
 finalize : function Finalize(key, reduced) {
	return reduced;
},
 out : { inline : 1 }
});

我用了一次,感觉效果还不错。现在也推荐给你试一下。

结果对象的结构如下:

{ "_id" : { "uuid" : "inmobi" , "url" : "static.51y5.net" } , "value" : { "count" : 82409.0}}
{ "_id" : { "uuid" : "inmobi" , "url" : "applet.kakamobi.com"} , "value" : { "count" : .23714.0}}

_id属性中是分组字段,value属性中保存结果对象。mongodb聚合函数产生的count是double类型的。你可以在finalize方法中处理一下,转换成整型。我是在java 代码转换的。

MongoDB的Mapreduce我也是第一次用,更具体的用法详解,待我研究之后,再做报告。因为我不愿意写完以后,再加点特技上去,文章“duang”一下,很赞,很劲,这样读者出来一定会骂我,博主根本就是不会,还装逼。(just kidding.)

以上内容有不对的地方,还望大家指正,虚心学习。

Thanks a lot ,END!

 

 

 

 

posted @ 2015-03-19 00:00  忙碌的键盘  阅读(508)  评论(0编辑  收藏  举报