シェルで例を提供しました。MR がこの問題の最善の解決策であるかどうかはわかりません。シングル スレッドの Javascript を避けるために、別の解決策を検討することをお勧めします。たとえば、当月のログインまたはメッセージのみを含む追加のフィールドを保存できます。ログインやメッセージを追加するたびに、カウンター フィールドをインクリメントします。このスキーマを使用すると、集計コマンドを使用せずに一致するドキュメントを見つけることができます。
また、MongoDB バージョン 2.2 (近日公開予定) で利用可能になる新しい集約フレームワークも検討する必要があります: http://docs.mongodb.org/manual/applications/aggregation/
最後に、パフォーマンスを向上させるために、MR コマンドにクエリを含めて、一致しないドキュメントを除外する必要があります (以下の例を参照)。
入力ドキュメント:
{ "_id" : 1, "name" : "Jenna", "height" : 100, "weight" : 51, "lastLogin" : [ 1, 2, 3, 4 ], "messageSentOn" : [ 4, 5, 5, 7 ] }
{ "_id" : 2, "name" : "Jim", "height" : 60, "weight" : 49, "lastLogin" : [ 2, 4 ], "messageSentOn" : [ 5, 6 ] }
{ "_id" : 3, "name" : "Jane", "height" : 90, "weight" : 60, "lastLogin" : [ 1 ], "messageSentOn" : [ 3, 6 ] }
{ "_id" : 4, "name" : "Joe", "height" : 70, "weight" : 65, "lastLogin" : [ 5, 6, 7 ], "messageSentOn" : [ 3, 6, 7 ] }
MR 機能:
map = function(){
var monthLogins = 0;
var monthMessages = 0;
var monthDate = 2;
for(var i=0; i<this.lastLogin.length; i++){
if(this.lastLogin[i] > monthDate){
monthLogins++;
}
}
for(var i=0; i<this.messageSentOn.length; i++){
if(this.messageSentOn[i] > monthDate){
monthMessages++;
}
}
if(monthLogins > 1 && monthMessages > 2)
{ emit(this._id, null);
}
}
reduce = function (key, values) {
//won't be called because a single document is emitted for each key
}
MR コマンド:
db.collection.mapReduce(map, reduce, {query: {weight: {$gt : 50}, height: {$gt: 5}, lastLogin: {$gt: 2}}, out: {inline:1}})
出力:
{"_id" : 1, "value" : null},
{"_id" : 4, "value" : null}