7

I would like to list currently deleted documents in order to provide the ability to undelete one or more.

How can I query couchdb for deleted documents? I am actually using pouchdb.

Although this POST nicely describes how to query for and undelete a document, it requires an id of an existing doc.

I am looking for a way to query for all documents that have been deleted. The POST cites making a query for all changes. That query returns all documents that have been deleted IN ADDITION to any that have been edited/changed.

I am looking only for documents that have been deleted. Think querying for documents in the 'trash bin'. :)

Bernhard Gschwantner
  • 1,547
  • 11
  • 12
Larry Eitel
  • 1,397
  • 5
  • 19
  • 37
  • Possible duplicate of [Retrieve just deleted document](https://stackoverflow.com/questions/10854883/retrieve-just-deleted-document) – Jonathan Hall Aug 13 '17 at 08:08
  • At this point I am thinking to add a deleted_at datetime value to each document. Using this I can emulate Laravel soft delete functionality. All my general queries would exclude docs with deleted_at value. That is unless there is a more elegant way to achieve this natively. – Larry Eitel Aug 15 '17 at 11:04

3 Answers3

8

Starting from couch 2.1.0, you can add various selectors to _changes feed. So your request to output only deleted documents will be:

curl -X POST -H "content-Type: application/json" "http://adm:pass@127.0.0.1:15984/tracks/_changes?filter=_selector" -d '{"selector": {"_deleted": true}}'

Mayya Sharipova
  • 405
  • 4
  • 11
4

You can add a filter to the _changes feed in PouchDB: https://pouchdb.com/api.html#filtered-changes

var changes = db.changes({
  filter: function(doc) {
    return doc._deleted;
  }
}).on('change', function(change) {
  console.log(change.id);
})
Bernhard Gschwantner
  • 1,547
  • 11
  • 12
1

For an all-in-one solution combining the open_revs tip from this answer, here's the TypeScript code I came up with:

const db = new PouchDB('my-db');

async function deletedDocIds(): Promise<string[]> {
  const ret: string[] = [];
  return new Promise((resolve, reject) => {
    db.changes({filter: d => d._deleted})
        .on('change', c => ret.push(c.id))
        .on('complete', () => resolve(ret))
        .on('error', e => reject(e));
  });
}

async function deletedDocs() {
  const ids = await deletedDocIds();
  return Promise.all(ids.map(id => db.get(id, {revs: true, open_revs: 'all'}).then(x => {
    const revs = (x[0].ok as any)._revisions;
    const lastRev = (revs.start - 1) + '-' + revs.ids[1];
    return db.get(id, {rev: lastRev}); // with Pouchdb keys too
  })));
}

Calling deletedDocs() will return a promise of an array of all deleted docs as per the rev just prior to deletion.

N.B., the elements of the array will include PouchDb metadata as well as your document's keys.

N.B. 2, version 6.1.3 of DefinitelyTyped's TypeScript bindings for pouchdb-browser which I'm using here (should work for @types/pouchdb too though) doesn't seem to know about the _revisions key, hence the as any escape hatch.

N.B. 3, this should be trivial to manually translate to plain JS, just delete the type declarations and coercions (:, as, and whatever token follows these).

Ahmed Fasih
  • 6,458
  • 7
  • 54
  • 95