One of CouchDB's most noteworthy features is the _changes
API. With it we can view all alterations to a database via HTTP.
For instance, to see all changes made to our quotes
database we can make a GET request to http://localhost:5984/quotes/_changes
. Even better, if we wanted to hook up to a live stream, we would add the query parameter ?feed=continuous
.
Cradle provides an attractive interface to the _changes
API, which we'll explore in this recipe.
We'll need a functioning CouchDB database and a way to write to it. We can use the quotes.js
example used in Storing data to CouchDB with Cradle, so let's copy that into a new directory and then create a file alongside it called quotes_stream.js
.
If we followed the Creating an admin user and Locking all modifying operations to an admin user sections of the previous recipe's There's more... section, we will need to modify the second line of quotes.js
in order to continue to insert quotes in our database:
var db = new (cradle.Connection)({ auth: { username: 'dave', password: 'cookit' }}) .database('quotes'),
Where dave
and cookit
are the example username and password.
We require cradle
and make a connection to our quotes
database. Our stream is intended for use with a pre-existing database, so we won't be checking for database existence.
var cradle = require('cradle'), var db = new (cradle.Connection)().database('quotes'),
Next, we call the changes
method of cradle
and listen to its response
event, in turn listening to the passed in response
emitter's data
event:
db.changes().on('response', function (response) { response.on('data', function (change) { var changeIsObj = {}.toString.call(change) === '[object Object]'; if (change.deleted !changeIsObj) { return; } db.get(change.id, function (err, doc) { if (!doc) {return;} if (doc.author && doc.quote) { console.log('%s: %s ', doc.author, doc.quote); } }); }); });
To test our changes
stream implementation we'll open two terminals. In one we'll run the following command:
node quotes_stream.js
In the other terminal window we can add some quotes using quotes.js:
node quotes.js "Yogi Berra" "I never said most of the things I said"
node quotes.js "Woody Allen" "I'd call him a sadistic hippophilic necrophile, but that would be beating a dead horse"
node quotes.js "Oliver Wendell Holmes" "Man's mind, once stretched by a new idea, never regains its original dimensions"
As each new quote is added in the left-hand terminal, it appears in the right.
quotes_stream.js
was opened up before any new quotes were added, and immediately displayed the Albert Einstein
quote which was added in the Storing data to CouchDB with Cradle recipe. After this, new quotes appeared in the stream as they were added.
The changes
method can be passed a callback, which simply returns all changes up to the present and then exits. If we do not pass a callback to changes
it adds the ?feed=continuous
parameter to the HTTP CouchDB REST call and returns EventEmitter
. CouchDB then returns a streamed HTTP response to Cradle which is sent through as the response
parameter of the response
event. The response
parameter is also EventEmitter
, and we listen for changes via the data
event.
On each data
event, the callback handles the change
parameter. Two data events are fired for each change, one is a JSON string, the other is a JavaScript object containing the equivalent JSON data. We check that the change
parameter's type is an object (changeIsObj
) before proceeding. The change
object holds metadata for our database entries. It has a sequence number (change.seq
), a revision number (change.changes[0].rev
), it sometimes contains a deleted property (changes.deleted
), and always has an id
property.
If the deleted
property is found, we need to return
early as db.get
can't fetch a deleted record. Otherwise, we pass change.id
into db.get
, which provides access to a document ID. The doc
is passed into the callback of db.get
. We only want to output changes regarding our quotes, so we check for author
and quote
fields and log them to the console.
52.14.130.13