0

これは本当に未解決の質問です。少し曖昧になってすみませんが、Mongoは初めてなので、他の人の考えを集めようとしています。

状況

  • コレクションに複数の重複ドキュメントがあることに気付きました(名前キーに基づく)
  • これらのドキュメントmay be sameまたはmight got changedファイルからの後続のダンプ中(後で変更を保持したい)
  • 挿入日がないため、どのドキュメントが最新かを確認するのは困難です(スキーマ設計が悪い)

募集

質問

  • ObjectIdに基づいて以前に挿入されたドキュメントを確認し、それを使用して削除することは可能Map Reduceですか?
  • 他に何か考えやアドバイスはありますか?
4

2 に答える 2

2

今夜は退屈なので、行きましょう。

ステップ 1. テストデータを準備しましょう。

> db.users.insert({name: 'John', other_field: Math.random()})
> db.users.insert({name: 'Bob', other_field: Math.random()})
> db.users.insert({name: 'Mary', other_field: Math.random()})
> db.users.insert({name: 'John', other_field: Math.random()})
> db.users.insert({name: 'Jeff', other_field: Math.random()})
> db.users.insert({name: 'Ivan', other_field: Math.random()})
> db.users.insert({name: 'Mary', other_field: Math.random()})
> db.users.find()
{
    "_id" : ObjectId("501976e9bee9b253265bba8b"),
    "name" : "John",
    "other_field" : 0.9884713875252772
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8c"),
    "name" : "Bob",
    "other_field" : 0.048004131996396415
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8d"),
    "name" : "Mary",
    "other_field" : 0.20415803582615222
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8e"),
    "name" : "John",
    "other_field" : 0.5514446987265585
}
{
    "_id" : ObjectId("501976e9bee9b253265bba8f"),
    "name" : "Jeff",
    "other_field" : 0.8685077449753242
}
{
    "_id" : ObjectId("501976e9bee9b253265bba90"),
    "name" : "Ivan",
    "other_field" : 0.2842514340422925
}
{
    "_id" : ObjectId("501976eabee9b253265bba91"),
    "name" : "Mary",
    "other_field" : 0.984048520281136
}

ステップ 2. map-reduce

var map = function() {
  emit(this.name, this);
};

var reduce = function(name, vals) {
  var last_obj = null;
  vals.forEach(function(v) {
    if(!last_obj || v._id > last_obj._id) {
      last_obj = v;
    }
  });
  return last_obj;
};

db.users.mapReduce(map, reduce, {out: 'temp_coll'})

基本的に、すべてのドキュメントを名前でグループ化し、最大のものを選択し_idます。

ステップ 3. 固有のデータを使用して何かを実行します。

> db.temp_coll.find()
{
    "_id" : "Bob",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba8c"),
        "name" : "Bob",
        "other_field" : 0.048004131996396415
    }
}
{
    "_id" : "Ivan",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba90"),
        "name" : "Ivan",
        "other_field" : 0.2842514340422925
    }
}
{
    "_id" : "Jeff",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba8f"),
        "name" : "Jeff",
        "other_field" : 0.8685077449753242
    }
}
{
    "_id" : "John",
    "value" : {
        "_id" : ObjectId("501976e9bee9b253265bba8e"),
        "name" : "John",
        "other_field" : 0.5514446987265585
    }
}
{
    "_id" : "Mary",
    "value" : {
        "_id" : ObjectId("501976eabee9b253265bba91"),
        "name" : "Mary",
        "other_field" : 0.984048520281136
    }
}

たとえば、元のコレクションを削除し、これを反復して新しいコレクションに値を挿入します。完了したら、一時コレクションを削除することを忘れないでください。

重要

objectid からのタイムスタンプの抽出については気にしませんでした。なぜなら、インポート ジョブを 1 秒に 2 回実行しないと想定していたからです (毎秒でさえないかもしれません)。

于 2012-08-01T18:49:52.157 に答える
0

オブジェクト ID は先頭の 4 バイトとしてタイムスタンプを使用するので、ちょっとした計算でこれを行うことができます。

ありがたいことに、mongo シェルには、オブジェクト ID からタイムスタンプを取得する方法があります。最初に同じ名前でドキュメントをクエリし、一時変数 (コマンド ラインを使用する場合) または一時テーブル (ドライバーを使用している場合) を取得し、以下のリンクに示されているタイムスタンプ ゲッターを使用して個々の ID を解析します。

http://www.mongodb.org/display/DOCS/Optimizing+Object+IDs#OptimizingObjectIDs-Extractinsertiontimesfromidratherthanhavingaseparatetimestampfield .

オブジェクト ID は秒単位までしか正確ではないため、高速挿入モードでは役に立たないことに注意してください。

しかし、どちらにしても、あなたが求めていることは、map reduce 関数で実行するか、コマンドラインから実行する上記の方法で実行できます。

試してみて、行き詰まったら教えてください。私があなたのコレクション構造を知っていれば、私はおそらく本当に素早く何かを作り上げることができますが、それはあなたがそれに数回頭をぶつけた後でのみです:)

于 2012-08-01T18:40:52.447 に答える