17

Mongo に一連のドキュメントがあります。言う:

[
    { summary:"This is good" },
    { summary:"This is bad" },
    { summary:"Something that is neither good nor bad" }
]

各単語の出現回数をカウントし (大文字と小文字を区別しない)、降順で並べ替えたいと思います。結果は次のようになります。

[
    "is": 3,
    "bad": 2,
    "good": 2,
    "this": 2,
    "neither": 1,
    "nor": 1,
    "something": 1,
    "that": 1
]

これを行う方法はありますか?私はすでにある程度理解しているので、集約フレームワークが好ましいでしょう:)

4

4 に答える 4

25

MapReduceは、クライアントで操作を行わずにサーバーでドキュメントを処理できる場合に適している可能性があります (DB サーバーで文字列を分割する機能がないため (未解決の問題))。

関数から始めmapます。以下の例 (より堅牢にする必要がある可能性があります) では、各ドキュメントがmap関数に (as としてthis) 渡されます。コードはsummaryフィールドを探し、そこにある場合は小文字化し、スペースで分割し、1見つかった単語ごとに for を出力します。

var map = function() {  
    var summary = this.summary;
    if (summary) { 
        // quick lowercase to normalize per your requirements
        summary = summary.toLowerCase().split(" "); 
        for (var i = summary.length - 1; i >= 0; i--) {
            // might want to remove punctuation, etc. here
            if (summary[i])  {      // make sure there's something
               emit(summary[i], 1); // store a 1 for each word
            }
        }
    }
};

次に、reduce関数内で、関数によって検出されたすべての結果を合計し、上記のmap単語ごとに個別の合計を返しますemit

var reduce = function( key, values ) {    
    var count = 0;    
    values.forEach(function(v) {            
        count +=v;    
    });
    return count;
}

最後に、mapReduce を実行します。

> db.so.mapReduce(map, reduce, {out: "word_count"})

サンプルデータの結果:

> db.word_count.find().sort({value:-1})
{ "_id" : "is", "value" : 3 }
{ "_id" : "bad", "value" : 2 }
{ "_id" : "good", "value" : 2 }
{ "_id" : "this", "value" : 2 }
{ "_id" : "neither", "value" : 1 }
{ "_id" : "or", "value" : 1 }
{ "_id" : "something", "value" : 1 }
{ "_id" : "that", "value" : 1 }
于 2013-04-23T18:10:05.417 に答える