CouchDB's RESTful API

Published 19:06 on 01 August, 2009

I’ve recently been playing with Apache CouchDB; a distributed, fault-tolerant and schema-free document-oriented database. CouchDB supplies a RESTful API for the manipulation of data within it. This is a great demonstration of REST at work, so I thought I’d illustrate its usage in a quick post.

Let’s get the technical details out of the way first: CouchDB makes use of HTTP verbs – GET, PUT, POST, and DELETE – and handles requests and responses in JSON only. This means it is entirely possible to utilise CouchDB using JavaScript alone. For the purpose of these examples, however, I’ll be using cURL, which is easier to follow along with via the command line.

My CouchDB server is running on my dev Ubuntu VM, on the default port of 5984. I’ve also set up a “couchhost” alias to the VM in my hosts file, to make my requests more readable.

Creating databases

The first thing we should do is create a database within our CouchDB server. To do that, we use the PUT verb:

$ curl -X PUT http://couchhost:5984/fu
{"ok":true}

In the command above, we specified the database name in the resource URI – which is the correct usage of PUT – and received a JSON object response. As you can see, that JSON object contains a single field; the boolean “ok”, with a value of true.

We can obtain a list of all the databases on our CouchDB server, by sending it a GET request to the _all_dbs resource:

$ curl -X GET http://couchhost:5984/_all_dbs
["fu"]

Here we receive an array response containing all our database ids. In this case, we only have our “fu” database.

Let’s try adding another:

$ curl -X PUT http://couchhost:5984/bar
{"ok":true}

Since we’ve received an ok response, let’s list all the databases again:

$ curl -X GET http://couchhost:5984/_all_dbs
["fu","bar"]

Now we can see multiple values in the array response.

We can obtain information about a specific database by sending a GET request to its URI:

$ curl -X GET http://couchhost:5984/fu
{"db_name":"fu","doc_count":0,"doc_del_count":0,"update_seq":0,"compact_running":false,"disk_size":4096}

Here we can see, amongst other things, the number of documents in the database – none – and how much diskspace the database is taking up – 4k.

CouchDB documents

A CouchDB document is simply a JSON object with some associated metadata. This is an example document (lifted from the CouchDB documentation):

{
    "_id":"discussion_tables",
    "_rev":"D1C946B7",
    "Sunrise":true,
    "Sunset":false,
    "FullHours":[1,2,3,4,5,6,7,8,9,10],
    "Activities":[
        {
            "Name":"Football",
            "Duration":2,
            "DurationUnit":"Hours"
        },
        {
            "Name":"Breakfast",
            "Duration":40,
            "DurationUnit":"Minutes",
            "Attendees":[
                "Jan",
                "Damien",
                "Laura",
                "Gwendolyn",
                "Roseanna"
            ]
        }
    ]
}

As you can see, a CouchDB document can handle multiple types of data, including arrays and nested objects. By default the structure is flat; in this particular case, the “Activities” attribute is structure imposed by the user.

It’s also worth noting that any top-level fields with a name that starts with an underscore prefix are reserved.

Adding documents

So let’s define a document for one of our databases:

{
    "FirstName":"Isabella",
    "FamilyName":"Huegdon",
    "Age":2,
    "Likes":[
        "noise",
        "animals",
        "chocolate",
        "kicking Milly",
        "throwing tantrums"
    ]
}

This is a fairly straight forward document that includes several different types of data. To add it to our database, let’s use an HTTP POST request:

$ curl -X POST http://couchhost:5984/fu \
-H 'Content-Type: application/json' \
-d '{"FirstName":"Isabella","FamilyName":"Huegdon","Age":2,"Likes":["noise","animals","chocolate","kicking Milly","throwing tantrums"]}'
{"ok":true,"id":"30d53965f5aec18391c258faa66921c1","rev":"2348720638"}

Because we’ve used POST, CouchDB has automagically assigned our document an identifier. You can see this in the id attribute of the response object. But what if we want to specify our own id? Simple; we use HTTP PUT instead.

Let’s define another document:

{
    "FirstName":"Amélie",
    "FamilyName":"Huegdon",
    "Age":2,
    "Likes":[
        "noise",
        "animals",
        "chocolate",
        "hitting Izzy",
        "running and screaming"
    ]
}

And now let’s add that document using HTTP PUT:

$ curl -X PUT http://couchhost:5984/fu/milly-huegdon \
-H 'Content-Type: application/json' \
-d '{"FirstName":"Amélie","FamilyName":"Huegdon","Age":2,"Likes":["noise","animals","chocolate","hitting Izzy","running and screaming"]}'
{"ok":true,"id":"milly-huegdon","rev":"3414255320"}

This time, we can see our specified id in the id attribute of the response object.

Now let’s have a look what documents we’ve got in the database, using the _all_docs resource, beneath our database:

$ curl -X GET http://couchhost:5984/fu/_all_docs
{
    "total_rows":2,
    "offset":0,
    "rows":[
        {
            "id":"30d53965f5aec18391c258faa66921c1",
            "key":"30d53965f5aec18391c258faa66921c1",
            "value":{"rev":"2348720638"}
        },
        {
            "id":"milly-huegdon",
            "key":"milly-huegdon",
            "value":{"rev":"3414255320"}
        }
    ]
}

Note: I’ve styled the response here for ease of reading; your cURL output will lack indenting but will contain the same information.

Here we can see, from the total_rows attribute, that there are 2 documents in our database; and we can see the metadata for those documents in the rows attribute array.

To obtain the actual document, we just need to send an HTTP GET request to the document’s URI:

$ curl -X GET http://couchhost:5984/fu/milly-huegdon
{
    "_id":"milly-huegdon",
    "_rev":"3414255320",
    "FirstName":"Am\u00e9lie",
    "FamilyName":"Huegdon",
    "Age":2,
    "Likes":[
        "noise",
        "animals",
        "chocolate",
        "hitting Izzy",
        "running and screaming"
    ]
}

Once again, I’ve styled the response somewhat for readability. In this instance, you can also see that CouchDB can handle unicode characters (since JSON should always be encoded as UTF-8) from the FirstName attribute.

Deleting items

Deletion of documents and databases from our CouchDB server couldn’t be simpler. All we need to do is send an HTTP DELETE request.

To remove the bar database we created earlier, we send the following request:

$ curl -X DELETE http://couchhost:5984/bar
{"ok":true}

Summary

You are now able to create and delete items from your CouchDB database. This is all you’re going to need if you just want to use CouchDB as a persistent document store; however, if you want to query the data in your databases, you’re going to need to make use of CouchDB Views. I’ll cover those in a later blog post.

I’m going to continue to play with CouchDB over the next week or so and will continue to blog about it (with the hope of using the blog posts as the basis for a TechTalk at Yahoo! Europe – slides possibly to follow on SlideShare). For now, you should be able to see that CouchDB is a wonderfully easy thing to use, thanks to its entirely RESTful API and its use of JSON as a request and response format.