MongoDB Group By操作、結果セットサイズ制限の問題.
問題が発生
会社はインターネット広告をして投入して、広告の展示量の上位500のドメイン名を統計する必要があります.最も簡単で乱暴な方法はgroup byで、urlによってグループを分けて、それからsortはすぐに日焼けをします!その結果、問題が発生しました.
2015-02-28当日22時のログ、ドキュメント数:904405を集計します.
エラー:
エラーメッセージが具体的ではなく、理解の問題もあり、集合中のドキュメントの数は20000を超えてはいけないと思います.2万はグループをサポートできません.何度もテストして、やっと私が間違っていることを証明しました.2万以上の結果セットはサポートされていません.つまり、グループ化されたドキュメントの数は2万を超えてはいけません.
この集合の唯一のurl数は20738で、ちょうど2万を超えているので、MongoDBのグループはどうしようもありません.
また,distinctは結果セットのサイズにも制限があることが意外に分かった.結果セットサイズは16 Mbを超えることはできません.
MongoDBはなぜこんなに制限が多く、閾値も小さいのか、大神さんに教えてもらいました.
問題を解決する
問題は解決するために使われて、stackoverflow大神の指摘を通じて、私はMongoDBのmapreduceでそれを解決しようとしましたが、実は最初は断っていました.あなたは私に使わせてはいけないので、私は使います.まず、私が使うかどうか見てみます.その結果、私は使えないことに気づき、MongoDBの説明ドキュメントを見ました.次のコードを書きます.
一度使いましたが、効果はまあまあだと思います.今でもお勧めします.
結果オブジェクトの構造は次のとおりです.
_id属性はパケットフィールド、value属性は結果オブジェクトを保存します.mongodb集約関数によって生成されるcountはdoubleタイプです.finalizeメソッドで処理して、整数に変換することができます.私はjavaコードで変換しました.
MongoDBのMapeduceは私も初めてで、もっと具体的な使い方は詳しくて、私が研究してから、報告します.私は书き终わった后に、更に特技をプラスしたくないので、文章は“duang”して、とてもすばらしくて、とても力があって、このように読者が出てきてきっと私をののしって、ブロガーは全然できなくて、また诘めています.(just kidding.)
以上の内容は間違っているところがあるので,皆さんに指摘してもらい,謙虚に勉強してください.
Thanks a lot ,END!
会社はインターネット広告をして投入して、広告の展示量の上位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!