ロールバックオプションはありません(ロールバックはMongoDBコンテキストでは異なる意味を持ちます)。厳密に言えば、これらのドキュメントを元に戻すためのサポートされている方法はありません。注意事項はコメントで説明されています。ただし、レプリカセットを実行している場合は、単一ノードのレプリカセットであっても、oplog
があります。 。 oplog
を使用 ドキュメントが挿入された時期をカバーしているので、ドキュメントを復元できる可能性があります。
これを説明する最も簡単な方法は、例を使用することです。復元する必要のある削除されたドキュメントを100個だけ使用した単純化された例を使用します。これを超えるには(膨大な数のドキュメント、または選択的にのみ復元したいなど)、コードを変更してカーソルを反復処理するか、MongoDBシェルの外部で選択した言語を使用してこれを記述します。基本的なロジックは同じです。
まず、サンプルコレクションfoo
を作成しましょう データベース内dropTest
。 name
なしで100個のドキュメントを挿入します フィールドと同じname
の100個のドキュメント 後で誤って削除できるようにフィールド:
use dropTest;
for(i=0; i < 100; i++){db.foo.insert({_id : i})};
for(i=100; i < 200; i++){db.foo.insert({_id : i, name : "some_x_name"})};
それでは、100個のname
の誤った削除をシミュレートしてみましょう。 ドキュメント:
> db.foo.remove({ "name" : "some_x_name"})
WriteResult({ "nRemoved" : 100 })
レプリカセットで実行しているため、これらのドキュメントの記録はoplog
に残っています。 (挿入されている)そしてありがたいことに、それらの挿入は(まだ)oplog
の終わりから落ちていません (oplog
上限のあるコレクションです覚えています)。それらを見つけることができるかどうか見てみましょう:
use local;
db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}).count();
100
カウントは正しいようですが、ドキュメントはまだ残っているようです。私は経験から、oplog
の唯一の部分であることを知っています ここで必要なエントリはo
です フィールドなので、それだけを返すようにプロジェクションを追加しましょう(簡潔にするために出力を切り取ったものですが、わかります):
db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}, {"o" : 1});
{ "o" : { "_id" : 100, "name" : "some_x_name" } }
{ "o" : { "_id" : 101, "name" : "some_x_name" } }
{ "o" : { "_id" : 102, "name" : "some_x_name" } }
{ "o" : { "_id" : 103, "name" : "some_x_name" } }
{ "o" : { "_id" : 104, "name" : "some_x_name" } }
これらのドキュメントを再挿入するには、それらを配列に格納してから、配列を繰り返し処理して、関連する部分を挿入します。まず、配列を作成しましょう:
var deletedDocs = db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}, {"o" : 1}).toArray();
> deletedDocs.length
100
次に、コレクションには現在100個のドキュメントしかないことを思い出し、100個の挿入をループして、最後にカウントを再検証します。
use dropTest;
db.foo.count();
100
// simple for loop to re-insert the relevant elements
for (var i = 0; i < deletedDocs.length; i++) {
db.foo.insert({_id : deletedDocs[i].o._id, name : deletedDocs[i].o.name});
}
// check total and name counts again
db.foo.count();
200
db.foo.count({name : "some_x_name"})
100
そして、いくつかの注意点がありますが、それがあります:
- コメントに記載されているように、これは真の復元戦略を意味するものではありません。バックアップ(MMS、その他)、そのための遅延セカンダリを確認してください。
- 大規模なビジー状態のシステムでは、oplogからドキュメントをクエリするのは特に迅速ではありません(oplogクエリはテーブルスキャンです)。
- ドキュメントはいつでもoplogから古くなる可能性があります(もちろん、後で使用するためにoplogのコピーを作成して、より多くの時間を与えることができます)
- ワークロードによっては、結果を再挿入する前に、結果の重複を排除する必要がある場合があります
- 示されているように、ドキュメントの大きなセットは配列に対して大きすぎるため、代わりにカーソルを反復処理する必要があります
-
oplog
の形式 内部と見なされ、いつでも(予告なしに)変更される可能性があるため、自己責任で使用してください