0

私はマップ削減の概念に不慣れで、進歩が遅いものの、助けが必要な問題をいくつか見つけています。

ID、都市、および目的地で構成される単純なコレクションがあります。次のようなものです。

{ "_id" : "5230e7e00000000000000000", "city" : "Boston", "to" : "Chicago" },
{ "_id" : "523fe7e00000000000000000", "city" : "New York", "to" : "Miami" },
{ "_id" : "5240e1e00000000000000000", "city" : "Boston", "to" : "Miami" },
{ "_id" : "536fe4e00000000000000000", "city" : "Washington D.C.", "to" : "Boston" },
{ "_id" : "53ffe7e00000000000000000", "city" : "New York", "to" : "Boston" },
{ "_id" : "5740e1e00000000000000000", "city" : "Boston", "to" : "Miami" },
...

(このデータは例として作成されていることに注意してください)

カウントを含む目的地を都市ごとにグループ化したいと思います。

{ "city" : "Boston", values : [{"Chicago",1}, {"Miami",2}] }
{ "city" : "New York", values : [{"Miami",1}, {"Boston",1}] }
{ "city" : "Washington D.C.", values : [{"Boston", 1}] }

このために、私はこの関数を使ってマッピングを始めています:

    function() {
        emit(this.city, this.to);
    }

期待されるグループ化を実行します。私のreduce関数はこれです:

    function(key, values) {
        var reduced = {"to":[]};

        for (var i in values) {
            var item = values[i];
            reduced.to.push(item);
        }

        return reduced;
    }

これにより、期待される出力がいくらか得られます。

{ "_id" : ObjectId("522f8a9181f01e671a853adb"), "value" : { "to" : [    "Boston", "Miami" ] } }
{ "_id" : ObjectId("522f933a81f01e671a853ade"), "value" : { "to" : [  "Chicago",  "Miami", "Miami" ] } }
{ "_id" : ObjectId("5231f0ed81f01e671a853ae0"), "value" : "Boston" }

ご覧のとおり、繰り返される都市はまだ数えていませんが、上記のように、何らかの理由で出力の最後の結果が良くありません。私はそれを期待していた

{ "_id" : ObjectId("5231f0ed81f01e671a853ae0"), "value" : { "to" : ["Boston"] } }

これは単品ということと何か関係があるのでしょうか?これを入手する方法はありますか?

ありがとうございました。

4

1 に答える 1

2

PHPの問題について質問されているようですが、JavaScriptを使用して質問しているため、JavaScriptの回答が物事を進めるのに役立つと思います。そのため、集計を実行するためにシェルで必要な JavaScript は次のとおりです。一般に、集計をシェル (または他の JavaScript エディター) で機能させてから、選択した言語に翻訳することを強くお勧めします。この方法を使用すると、何が起こっているかを確認するのがはるかに簡単になり、より速くなります。その後、次を実行できます。

use admin
db.runCommand( { setParameter: 1, logLevel: 2 } )

選択した言語の bson 出力とシェルの外観を確認します。これは、mongo がフォアグラウンドにある場合はターミナルに表示されます。それ以外の場合は、ログを確認する必要はありません。

アグリゲーション フレームワーク [AF] で Mongo を使用してルートを合計するのは、かなり簡単です。AF は map reduce[MR] よりも高速で使いやすいです。この場合、両方とも同様の問題がありますが、単純に配列にプッシュしても、それ自体ではカウントが得られません (MR では、reduce 関数でより多くのロジックが必要になるか、ファイナライズ関数を使用する必要があります)。

提供されたサンプル データを使用する AF では、このパイプラインが役立ちます。

db.agg1.aggregate([
     {$group:{
         _id: { city: "$city", to: "$to" },  
         count: { $sum: 1 }
     }},
     {$group: {
         _id: "$_id.city",
         to:{ $push: {to: "$_id.to", count: "$count"}}
     }}
]);

集計フレームワークは既知のフィールドでのみ操作できますが、多くのパイプライン操作があるため、問題はそれを考慮して分解する必要があります。上記の第 1 段階では、必要な数が計算されます。これには、ソース、宛先、およびカウントの 3 つの固定フィールドがあります。第 2 ステージには 2 つの固定フィールドがあり、そのうちの 1 つは配列で、プッシュされるだけです (最終フォームのすべてのデータがそこにあります)。

MRの場合、これを行うことができます:

var map = function() {
    var key = {source:this.city, dest:this.to};
    emit(key, 1);
};

var reduce = function(key, values) {
    return Array.sum(values);
};

ただし、別の関数できれいにする必要があります。

他にご不明な点がございましたら、お気軽にお問い合わせください。

ベスト、チャーリー

于 2013-09-18T22:17:39.590 に答える