Up tonight, I try to get started with a simple node.js / CouchDB application. I am a big fan of CouchDB with node.js because CouchDB speaks HTTP natively. There is no need for middleware or data drivers with CouchDB—I can just make HTTP requests and process the response or send it along to the client.
I already have the latest node.js installed and a CouchDB server running.
My first step is to create a simple express.js application to play with:
➜ repos express calendar create : calendar create : calendar/package.json create : calendar/app.js create : calendar/public/stylesheets create : calendar/public/stylesheets/style.css create : calendar/public/javascripts create : calendar/public/images create : calendar/views create : calendar/views/layout.jade create : calendar/views/index.jadeIn the new "calendar" app directory, I need to install the express and jade packages from npm:
➜ calendar git:(master) ✗ npm install express jade jade@0.14.2 ./node_modules/jade express-unstable@2.4.3 ./node_modules/express ├── mime@1.2.2 ├── connect@1.6.0 └── qs@0.3.1My next step is to use the Futon admin interface to create a database. I fancy a calendar app, so I name my database accordingly:
Next, I create a calendar event:
And an event for tomorrow:
To allow my simple express.js app to pass those events back to the browser, I need to establish a route for all events. In that route, I access the special
_all_docs
resource in CouchDB to pull back all records in the calendar DB (I prolly would not do that in a larger DB). Once the Couch DB response comes back, I write the data back to the browser:app.get('/events', function(req, res){ var options = { host: 'localhost', port: 5984, path: '/calendar/_all_docs' }; http.get(options, function(couch_response) { console.log("Got response: %s %s:%d%s", couch_response.statusCode, options.host, options.port, options.path); res.contentType('json'); // Send all couch data to the client couch_response.on('data', function (chunk) { res.write(chunk); }); // When couch is done, so is this request couch_response.on('end', function (chunk) { res.end(); }); }).on('error', function(e) { console.log("Got error: " + e.message); }); });That's a bit of work establishing 'data' and 'end' listeners. Fortunately, node has an answer for this case in the
pipe
method for all stream objects:http.get(options, function(couch_response) { console.log("Got response: %s %s:%d%s", couch_response.statusCode, options.host, options.port, options.path); couch_response.pipe(res) })Any events emitted by couch_response will be sent to the original Response object. The result of calling accessing the
/events
resource is:As can be seen in the screen shot, the actual event data is not being returned—just IDs and other metadata. To get the full event, I can create another express.js route with a similar callback:
app.get('/events/:id', function(req, res){ var options = { host: 'localhost', port: 5984, path: '/calendar/' + req.params.id }; http.get(options, function(couch_response) { console.log("Got response: %s %s:%d%s", couch_response.statusCode, options.host, options.port, options.path); couch_response.pipe(res); }).on('error', function(e) { console.log("Got error: " + e.message); }); });This route makes use of some nifty parameter assignments in express.js. Named parameters in the route (the
:id
in /events/:id
) are made available in the request params object (e.g. req.params.id
). That bit of coolness aside, this is nearly identical to the all-events route from above.That is all well and good, but I do not think that I want my client making dozens of calls to this resource for each event on a particular calendar. Instead, I go back into my
/events
route and add include_docs=true
to the URL. This includes the documents (which are relatively small) along with the meta data:Cool beans. That is a good stopping point for tonight. Tomorrow I will hook those into jQuery Ajax calls to build a month-view calendar. And then the fun begins with a backbone.js equivalent.
Day #124
Hello Chris,
ReplyDeleteI have a quick question please. I am just starting on this series and I am a total CouchDB n00b. I notice that the screen-shots for 'I create a calendar event' and 'an event for tomorrow' are the same. Is this intended? Could you pls. take a second and pls. fix or point me to some related info.
thanks a bunch
If you look closely, the two screenshots are different. The attribute keys (title, startDate, etc) are the same, but the values (2011-08-25, 2011-08-26) are different.
ReplyDeleteGood luck following along with the series. I didn't really write it with the idea that people would try to recreate the code / DB. Hopefully there won't be too many gaps along the way.
Source is here: https://github.com/eee-c/Funky-Backbone.js-Calendar (much of it is in branches).
Hope that helps.
-Chris
Yes, it does. Thanks a lot
ReplyDeleteI am planning to work through the series since I like to work in a similar fashion when trying to explore a new topic /language.
I will try to keep the questions to a minimum though :D
thanks again
Hi Chris
ReplyDeleteI am really new to this so need a little help. Actualy i am trying to get data from couchdb n display it on the page using backbone.js. so in your example after u create the calender database you hav used the backbone.js code to route the events ryt? i want to knw where exactly do u execute that code..?? where do u have to write it?
Actually, there isn't any Backbone code in this post. All of this was in the express.js webserver which I'm using here to read from CouchDB and send to the browser in a REST-like JSON format. The routing that I talk about in this post is server-side, express.js routing -- not Backbone routing.
DeleteI start the converting to Backbone.js a few days later: http://japhr.blogspot.com/2011/08/converting-to-backbonejs.html.
The end result is at: https://github.com/eee-c/Funky-Backbone.js-Calendar, but if you keep following the "next" links at the top of this page, I try to explain my entire process -- perhaps it could be of some use?