-
-
Save jofomah/ffb7a3cbb2e4710f05b2e4f3c4db35da to your computer and use it in GitHub Desktop.
Node.JS CouchDB paginator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cradle = require('cradle'); | |
// change as necessary | |
var host = '127.0.0.1'; | |
var port = 5984; | |
var dbname = 'foo'; | |
// setup cradle db and paginator | |
var conn = new (cradle.Connection)(host, port); | |
var db = conn.database(dbname); | |
var paginator = new Paginator(db, 'some/view'); | |
paginator.on('rows', function(rows){ | |
if (rows.length) { | |
rows.forEach(function(row) { | |
// do something with the row | |
}); | |
// get the next batch of rows | |
paginator.next(); | |
} | |
}); | |
// start getting rows | |
paginator.next(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var events = require('events'), | |
util = require('util'); | |
/** | |
* Utility for paging through a couchdb database. | |
* | |
* @param db | |
* (instance) Instance of a 'cradle' db object | |
* | |
* @param pageSize | |
* (integer) Optional rows per page. Default = 10. | |
* | |
* Paginator emits the following signals: | |
* | |
* 'rows' - A list of rows read from couch. [] if none or at end. | |
* 'error' - Error reading from database. | |
*/ | |
var Paginator = function Paginator(db, view, pageSize) { | |
events.EventEmitter.call(this); | |
this.init(db, view, pageSize); | |
return this; | |
}; | |
util.inherits(Paginator, events.EventEmitter); | |
Paginator.prototype.init = function(db, view, pageSize) { | |
this.db = db; | |
this.view = view; | |
this.pageSize = pageSize || 10; | |
this._startkey_docid = 0; | |
this._startkey = 0; | |
this._done = false; | |
}; | |
Paginator.prototype.end = function() { | |
this.db = null; | |
this.removeAllListeners(); | |
}; | |
/** | |
* Emit next page (group of rows) from the db. | |
* | |
* @param count | |
* (integer) How many rows to fetch. Default=10. | |
* | |
*/ | |
Paginator.prototype.next = function(count) { | |
if (this._done) { | |
this.emit('rows', []); | |
return; | |
} | |
count = count || this.pageSize; | |
//Pagination algorithm from guide.couchdb.org: | |
// | |
// - Request 'count' + 1 rows from the view | |
// - Emit 'count' rows, store + 1 row as next _startkey and _startkey_docid | |
// - Use the _next_* values to query the subsequent pages | |
this.db.view(this.view, { | |
startkey_docid: this._startkey_docid, | |
startkey: this._startkey, | |
limit: count+1 | |
}, function(err, docs) { | |
if (err) { | |
this.emit('error', "Database error: " + err); | |
return; | |
} | |
var rows = docs.length; | |
if (rows < count + 1) { | |
// Read last docs in db | |
this._done = true; | |
this.emit('rows', docs); | |
} else { | |
var nextStartDoc = docs[rows-1]; | |
this._startkey_docid = nextStartDoc.id; | |
this._startkey = nextStartDoc.key; | |
this.emit('rows', docs.slice(0, count)); | |
} | |
}.bind(this)); | |
}; | |
module.exports = Paginator; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment