MongoDB Group By操作、結果セットサイズ制限の問題.


問題が発生
会社はインターネット広告をして投入して、広告の展示量の上位500のドメイン名を統計する必要があります.最も簡単で乱暴な方法は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万はグループをサポートできません.何度もテストして、やっと私が間違っていることを証明しました.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のグループはどうしようもありません.
また,distinctは結果セットのサイズにも制限があることが意外に分かった.結果セットサイズは16 Mbを超えることはできません.
> 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のMapeduceは私も初めてで、もっと具体的な使い方は詳しくて、私が研究してから、報告します.私は书き终わった后に、更に特技をプラスしたくないので、文章は“duang”して、とてもすばらしくて、とても力があって、このように読者が出てきてきっと私をののしって、ブロガーは全然できなくて、また诘めています.(just kidding.)
以上の内容は間違っているところがあるので,皆さんに指摘してもらい,謙虚に勉強してください.
Thanks a lot ,END!