2

私はmongo dbを初めて使用するので、これが些細なことであればすみません。本当に助かります。

アイデアは、いくつかの特定の値に対してヒストグラムを生成することです。その場合、一部のファイルの MIME タイプ。そのために、マップ削減ジョブを使用しています。

次の形式のドキュメントを含むmongoがあります。

{
    "_id" : ObjectId("4fc5ed3e67960de6794dd21c"),
    "name" : "some name",
    "uid" : "some app specific uid",
    "collection" : "some name",
    "metadata" : [
        {
            "key" : "key1",
            "value" : "Plain text",
            "status" : "SINGLE_RESULT",
        },
        {
            "key" : "key2",
            "value" : "text/plain",
            "status" : "SINGLE_RESULT",
        },
        {
            "key" : "key3",
            "value" : 3469,
            "status" : "OK",
        }
     ]
}

ほとんどすべてのドキュメントには、より多くのメタデータ キー値があることに注意してください。

Map Reduce ジョブ

私は次のことを試しました:

function map() {
   var mime = "";
   this.metadata.forEach(function (m) {
     if (m.key === "key2") {
        mime = m.value;}
     });
     emit(mime, {count:1});
}

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

db.collection.mapReduce(map, reduce, {out: { inline : 1}})

これは少数のドキュメント (~15K) では機能するようですが、問題は、マッピング フェーズですべてのメタデータ キー値を反復処理するのに多くの時間がかかることです。これをより多くのドキュメント (~1Mio) で実行すると、操作に時間がかかります。

私の質問は次のとおりです。すべてのキーを反復処理して選択する代わりに、MIME タイプ (値) を直接発行できる方法はありますか? または、map reduce 関数を作成するより良い方法はありますか。

emit (this.metadata.value {$where this.metadata.key:"key2"}) などのようなもの...

ご協力いただきありがとうございます!

4

1 に答える 1

6

二つの思い…

最初の考え: このドキュメント スキーマにどの程度愛着がありますか? 次のように、埋め込み配列ではなく、埋め込みドキュメントとしてメタデータ フィールドの値を使用できますか。

{
    "_id" : ObjectId("4fc5ed3e67960de6794dd21c"),
    "name" : "some name",
    "uid" : "some app specific uid",
    "collection" : "some name",
    "metadata" : {
        "key1" : {
            "value" : "Plain text",
            "status" : "SINGLE_RESULT"
        },
        "key2": {
            "value" : "text/plain",
            "status" : "SINGLE_RESULT"
        }, 
        "key3" : {
            "value" : 3469,
            "status" : "OK"
        }
     }
}

次に、マップ ステップでループが完全になくなります。

function map() {
   emit( this.metadata["key2"].value, { count : 1 } );
}

その時点で、これを「mapReduce」ではなく「グループ」コマンドとしてキャストすることさえできるかもしれません。

再考: そのようなスキーマの変更がない場合、特に "key2" がメタデータ配列の早い段階で現れる場合は、次のように、キーが見つかったら少なくともループを積極的に終了して、反復を節約できます。

function map() {
   var mime = "";
   this.metadata.forEach(function (m) {
     if (m.key === "key2") {
        mime = m.value;
        break;
     } 
     });
     emit(mime, {count:1});
}

どちらの道が勝利への鍵であるかはわかりませんが、うまくいけば役立つ考えです. 頑張ってください!

于 2012-05-30T17:58:44.433 に答える