Recover deleted documents?

Hi @Georgios_Petasis and welcome in the MongoDB Community :muscle: !

If you have a standalone mongod, then no, it’s lost forever.
If you have a Replica Set (even a single node), then it means all the write operations are written to the Oplog.

The Oplog is a system collection that has a limited size (capped collection) and overwrite the oldest entries as new ones arrive.

You can retrieve information about your Oplog with the command:

> db.getReplicationInfo()
{
  logSizeMB: 8423,
  usedMB: 0.01,
  timeDiff: 360,
  timeDiffHours: 0.1,
  tFirst: 'Wed Sep 29 2021 14:35:23 GMT+0000 (Coordinated Universal Time)',
  tLast: 'Wed Sep 29 2021 14:41:23 GMT+0000 (Coordinated Universal Time)',
  now: 'Wed Sep 29 2021 14:41:30 GMT+0000 (Coordinated Universal Time)'
}

Depending how much write operations are performed on the cluster, the oplog time window can be large or small. It’s a good practice to have a confortable size.

If you inserted these documents recently and if you have a large oplog windows, they are still in the oplog.

See this little example:

test [direct: primary] test> db.coll.insertMany([{name: "Max"}, {name: "Alex"}, {name: "Claire"}])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("61547bd83bbc8bc533a5c784"),
    '1': ObjectId("61547bd83bbc8bc533a5c785"),
    '2': ObjectId("61547bd83bbc8bc533a5c786")
  }
}
test [direct: primary] test> db.coll.deleteMany({})
{ acknowledged: true, deletedCount: 3 }
test [direct: primary] test> use local
switched to db local
test [direct: primary] local> db.oplog.rs.find({op: 'i', ns: 'test.coll'}, {o:1})
[
  { o: { _id: ObjectId("61547bd83bbc8bc533a5c784"), name: 'Max' } },
  { o: { _id: ObjectId("61547bd83bbc8bc533a5c785"), name: 'Alex' } },
  { o: { _id: ObjectId("61547bd83bbc8bc533a5c786"), name: 'Claire' } }
]

With an aggregation pipeline, I can even restore them into the original collection:

test [direct: primary] local> db.oplog.rs.aggregate([{$match: {op: 'i', ns: 'test.coll'}},{$replaceRoot: {newRoot: '$o'}}, { $merge: { into: {db: "test", coll: "coll"}, on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }])

test [direct: primary] local> use test 
switched to db test
test [direct: primary] test> db.coll.find()
[
  { _id: ObjectId("61547bd83bbc8bc533a5c784"), name: 'Max' },
  { _id: ObjectId("61547bd83bbc8bc533a5c785"), name: 'Alex' },
  { _id: ObjectId("61547bd83bbc8bc533a5c786"), name: 'Claire' }
]

Cheers,
Maxime.

2 Likes