I have removed some documents in my last query by mistake, Is there any way to rollback my last query mongo collection.
Here it is my last query :
db.foo.remove({ "name" : "some_x_name"})
Is there any rollback/undo option? Can I get my data back?
There is no rollback option (rollback has a different meaning in a MongoDB context), and strictly speaking there is no supported way to get these documents back - the precautions you can/should take are covered in the comments. With that said however, if you are running a replica set, even a single node replica set, then you have an
oplog
. With anoplog
that covers when the documents were inserted, you may be able to recover them.The easiest way to illustrate this is with an example. I will use a simplified example with just 100 deleted documents that need to be restored. To go beyond this (huge number of documents, or perhaps you wish to only selectively restore etc.) you will either want to change the code to iterate over a cursor or write this using your language of choice outside the MongoDB shell. The basic logic remains the same.
First, let's create our example collection
foo
in the databasedropTest
. We will insert 100 documents without aname
field and 100 documents with an identicalname
field so that they can be mistakenly removed later:Now, let's simulate the accidental removal of our 100
name
documents:Because we are running in a replica set, we still have a record of these documents in the
oplog
(being inserted) and thankfully those inserts have not (yet) fallen off the end of theoplog
(theoplog
is a capped collection remember) . Let's see if we can find them:The count looks correct, we seem to have our documents still. I know from experience that the only piece of the
oplog
entry we will need here is theo
field, so let's add a projection to only return that (output snipped for brevity, but you get the idea):To re-insert those documents, we can just store them in an array, then iterate over the array and insert the relevant pieces. First, let's create our array:
Next we remind ourselves that we only have 100 docs in the collection now, then loop over the 100 inserts, and finally revalidate our counts:
And there you have it, with some caveats:
oplog
is considered internal and may change at any time (without notice), so use at your own riskWhile I understand this is a bit old but I wanted to share something that I researched in this area that may be useful to others with a similar problem.
The fact is that MongoDB does not Physically delete data immediately - it only marks it for deletion. This is however version specific and there is currently no documentation or standardization - which could enable a third party tool developer (or someone in desperate need) to build a tool or write a simple script reliably that works across versions. I opened a ticket for this - https://jira.mongodb.org/browse/DOCS-5151.
I did explore one option which is at a much lower level and may need fine tuning based on the version of MongoDB used. Understandably too low level for most people's linking, however it works and can be handy when all else fails.
My approach involves directly working with the binary in the file and using a Python script (or commands) to identify, read and unpack (BSON) the deleted data.
My approach is inspired by this GitHub project (I am NOT the developer of this project). Here on my blog I have tried to simplify the script and extract a specific deleted record from a Raw MongoDB file.
Currently a record is marked for deletion as "
\xee
" at the start of the record. This is what a deleted record looks like in the raw db file,I replaced the first block with the size of the record which I identified earlier based on other records.
Finally using the BSON package (that comes with pymongo), I decoded the binary to a Readable object.
This BSON is a python object now and can be dumped into a recover collection or simply logged somewhere.
Needless to say this or any other recovery technique should be ideally done in a staging area on a backup copy of the database file.