29

I deleted a document but I can still see it in _changes, so I can see last valid _rev, which is deleted, so get doc with id and last revision just returns:

{
  "_id":"25efa4ec8489d8b89b34c5cad6000059",
  "_rev":"3-a982bd6dccce8f405433f8453ab86880",
  "_deleted":true
}

and no other attributes.

How can I recover in this situation? Previous revision can not be seen in _changes. Will writing empty document (setting _deleted to false) help to see all revisions info?

Simon
  • 31,675
  • 9
  • 80
  • 92
avalez
  • 1,217
  • 1
  • 10
  • 15
  • Based on this question it should be possible: http://stackoverflow.com/questions/4738522/couchdb-change-notifications – avalez Jun 01 '12 at 17:42

3 Answers3

54

Ok, figured it out, if anyone interested:

  1. get deleted history, e.g.:

    curl http://example.iriscouch.com/test/_changes
    
  2. you'll see deleted documents with $id and $rev, put empty document as new version, e.g.:

    curl -X PUT http://example.iriscouch.com/test/$id?rev=$rev -H "Content-Type: application/json" -d {}
    
  3. now you can get all revisions info, e.g:

    curl http://example.iriscouch.com/test/$id?revs_info=true
    
  4. obtain version before deletion, e.g.:

    curl http://example.iriscouch.com/test/$id?rev=$prev_rev
    
  5. put it back to couchdb, e.g.:

    curl -X PUT http://example.iriscouch.com/test/$id?rev=$rev -H \'Content-Type: application/json\' -d \'$data\'
    

Let me know if you have any better way, or script.

Simon
  • 31,675
  • 9
  • 80
  • 92
avalez
  • 1,217
  • 1
  • 10
  • 15
  • 5
    Do you know why on step 2 I get - {"error"=>"conflict", "reason"=>"Document update conflict."} ? – vladCovaliov May 28 '15 at 09:32
  • This was extremely useful - thanks for the clear, step-by-step instructions. Most of this could be done via Futon, but there are a few steps that you really do need to run via CLI. Unfortunately, this isn't widely documented. – StickByAtlas Feb 24 '17 at 00:26
  • 1
    not working for me , it says `{"error":"not_found","reason":"missing"}` , how to fetch the all revisions data – ganesh Apr 30 '18 at 07:13
  • I'm getting `{"error":"forbidden","reason":"Usernames can not be changed."} ` : ( – Costa Michailidis Jan 24 '19 at 21:57
  • this is a good shortcut: https://docs.couchdb.org/en/stable/api/document/common.html#copying-from-a-specific-revision See my answer for details – Paolo Sanchi Sep 02 '20 at 08:05
19

Just been restoring deleted data from a couchdb. This is how I solved it after a little help from the good people on couchdb irc.

1) A get request to $db/$id?revs=true&open_revs=all where $db is your database name and $id is the id of the doc you deleted.

2) Clean the response. The result of this request wasn't valid json, strangely, and required cleaning. The following worked for me:

var deletedDoc = JSON.parse(xhReq.responseText.substring(xhReq.responseText.indexOf("{"), xhReq.responseText.lastIndexOf("}") + 1));

The resulting object looks like this:

  {
       "_id":"37b580b03b903da2b50f88587d89c15d",
       "_rev":"2-bf3a2888dfe1ce0facef18720dcf97e2",
       "_deleted":true,
       "_revisions":{
              "start":2,
              "ids":["bf3a2888dfe1ce0facef18720dcf97e2","85f141069731f6bc77c910b0341e599f"]
             }
     }

3) Now we can construct the last revision number, the one before it was deleted. Pull out the second guid in the _revisions.ids array and append it with _revisions.start - 1 and a "-" character. This gives you the rev id of the document just before it was deleted.

var preDeleteRevisionNumber = (deletedDoc._revisions.start - 1) + "-"+ deletedDoc._revisions.ids[1];

4) Now collect the original (predelete data) with a get to $db/$id?rev=$preDeleteRevisionNumber

5) To overwrite the old deleted entry you have to post or put back the document with the correct id and the latest revision number (not the pre delete revision number, but the revision number the document has now it has been deleted).

Hope this helps someone.

TABlackmore
  • 191
  • 1
  • 3
  • 1
    I know this is a reallllly old thread, but you can get valid JSON if you ask for it. For example, using curl: `curl -H 'Accept: application/json' 'http://127.0.0.1:5984/$db/$id?revs=true&open_revs=all`. – agregoire Nov 29 '16 at 14:01
  • Five years old, but still the best answer. Note if you're using PouchDB, the response comes back as JSON. – rickb Mar 19 '18 at 23:30
5

I found an easy way to restore a deleted document, just copy the previous (undeleted) revision to "itself". It works perfectly with attachments too.

https://docs.couchdb.org/en/stable/api/document/common.html#copying-from-a-specific-revision

After you found the id and rev of you document (as avalez explained: https://stackoverflow.com/a/10857330/846168)

Instead of retrieving data and put it back, just use the action COPY with it's $id as destination:

COPY http://example.iriscouch.com/test/$id?rev=$rev HTTP/1.1
Accept: application/json
Destination: $id

or with curl:

curl -X COPY "http://example.iriscouch.com/test/$id?rev=$rev" -H "Destination: $id"
gesellix
  • 3,024
  • 28
  • 31
Paolo Sanchi
  • 783
  • 9
  • 19
  • I think this is the only correct way to do it, as an intermediate empty document can cause harm. – Tino Jul 25 '21 at 15:21