3
votes

TL;DR: I want a PouchDB db that acts like Ember Data: fetch from the local store first, and if not found, go to the remote. Replicate only that document in both cases.

I have a single document type called Post in my PouchDB/CouchDB servers. I want PouchDB to look at the local store, and if it has the document, return the document and start replicating. If not, go to the remote CouchDB server, fetch the document, store it in the local PouchDB instance, then start replicating only that document. I don't want to replicate the entire DB in this case, only things the user has already fetched.

I could achieve it by writing something like this:

var local = new PouchDB('local');
var remote = new PouchDB('http://localhost:5984/posts');

function getDocument(id) {
  return local.get(id).catch(function(err) {
    if (err.status === 404) {
      return remote.get(id).then(function(doc) {
        return local.put(id);
      });
    }
    throw error;
  });
}

This doesn't handle the replication issue either, but it's the general direction of what I want to do.

I can write this code myself I guess, but I'm wondering if there's some built-in way to do this.

1

1 Answers

4
votes

Unfortunately what you describe doesn't quite exist (at least as a built-in function). You can definitely fall back from local to remote using the code above (which is perfect BTW :)), but local.put() will give you problems, because the local doc will end up with a different _rev than the remote doc, which could mess with replication later on down the line (it would be interpreted as a conflict).

You should be able to use {revs: true} to fetch the doc with its revision history, then insert with {new_edits: false} to properly replicate the missing doc, while preserving revision history (this is what the replicator does under the hood). That would look like this:

var local = new PouchDB('local');
var remote = new PouchDB('http://localhost:5984/posts');

function getDocument(id) {
  return local.get(id).catch(function(err) {
    if (err.status === 404) {
      // revs: true gives us the critical "_revisions" object,
      // which contains the revision history metadata
      return remote.get(id, {revs: true}).then(function(doc) {
        // new_edits: false inserts the doc while preserving revision
        // history, which is equivalent to what replication does
        return local.bulkDocs([doc], {new_edits: false});
      }).then(function () {
        return local.get(id); // finally, return the doc to the user
      });
    }
    throw error;
  });
}

That should work! Let me know if that helps.