Getting Started with CouchDB and Futon

Exclusive offer: get 50% off this eBook here
CouchDB and PHP Web Development Beginner's Guide

CouchDB and PHP Web Development Beginner's Guide — Save 50%

Get your PHP application from conception to deployment by leveraging CouchDB's robust features with this book and ebook.

$26.99    $13.50
by Tim Juravich | November 2012 | Open Source PHP Web Development

CouchDB is a NoSQL database which is making waves in the development world. It’s the tool of choice for many PHP developers so they need to understand the robust features of CouchDB and the tools that are available to them.

This article by Tim Juravich, author of CouchDB and PHP Web Development Beginner's Guide, defines CouchDB documents and shows how to manage them both from the command-line and within Futon – CouchDB's built-in administration utility.

(For more resources related to this topic, see here.)

What is CouchDB?

The first sentence of CouchDB's definition (as defined by http://couchdb.apache.org/) is as follows:

CouchDB is a document database server, accessible through the RESTful JSON API.

Let's dissect this sentence to fully understand what it means. Let's start with the term database server.

Database server

CouchDB employs a document-oriented database management system that serves a flat collection of documents with no schema, grouping, or hierarchy. This is a concept that NoSQL has introduced, and is a big departure from relational databases (such as MySQL), where you would expect to see tables, relationships, and foreign keys. Every developer has experienced a project where they have had to force a relational database schema into a project that really didn't require the rigidity of tables and complex relationships. This is where CouchDB does things differently; it stores all of the data in a self-contained object with no set schema. The following diagram will help to illustrate this:

In order to handle the ability for many users to belong to one-to-many groups in a relational database (such as MySQL), we would create a users table, a groups table, and a link table, called users_groups. This practice is common to most web applications.

Now look at the CouchDB documents. There are no tables or link tables, just documents. These documents contain all of the data pertaining to a single object.

This diagram is very simplified. If we wanted to create more logic around the groups in CouchDB, we would have had to create group documents, with a simple relationship between the user documents and group documents.

Let's dig into what documents are and how CouchDB uses them.

Documents

To illustrate how you might use documents, first imagine that you are physically filling out the paper form of a job application. This form has information about you, your address, and past addresses. It also has information about many of your past jobs, education, certifications, and much more. A document would save all of this data exactly in the way you would see it in the physical form - all in one place, without any unnecessary complexity.

In CouchDB, documents are stored as JSON objects that contain key and value pairs. Each document has reserved fields for metadata such as id, revision, and deleted. Besides the reserved fields, documents are 100 percent schema-less, meaning that each document can be formatted and treated independently with as many different variations as you might need.

Example of a CouchDB document

Let's take a look at an example of what a CouchDB document might look like for a blog post:

{ "_id": "431f956fa44b3629ba924eab05000553", "_rev": "1-c46916a8efe63fb8fec6d097007bd1c6", "title": "Why I like Chicken", "author": "Tim Juravich", "tags": [ "Chicken", "Grilled", "Tasty" ], "body": "I like chicken, especially when it's grilled." }

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

JSON format

The first thing you might notice is the strange markup of the document, which is JavaScript Object Notation (JSON). JSON is a lightweight data-interchange format based on JavaScript syntax and is extremely portable. CouchDB uses JSON for all communication with it.

Key-value storage

The next thing that you might notice is that there is a lot of information in this document. There are key-value pairs that are simple to understand, such as "title", "author", and "body", but you'll also notice that "tags" is an array of strings. CouchDB lets you embed as much information as you want directly into a document. This is a concept that might be new to relational database users who are used to normalized and structured databases.

Reserved fields

Let's look at the two reserved fields: _id and _rev.

_id is the unique identifier of the document. This means that _id is mandatory, and no two documents can have the same value. If you don't define an _id on creation of a document, CouchDB will choose a unique one for you.

_rev is the revision version of the document and is the field that helps drive CouchDB's version control system. Each time you save a document, the revision number is required so that CouchDB knows which version of the document is the newest. This is required because CouchDB does not use a locking mechanism, meaning that if two people are updating a document at the same time, then the first one to save his/her changes first, wins. One of the unique things about CouchDB's revision system is that each time a document is saved, the original document is not overwritten, and a new document is created with the new data, while CouchDB stores a backup of the previous documents in its original form in an archive. Old revisions remain available until the database is compacted, or some cleanup action occurs.

The last piece of the definition sentence is the RESTful JSON API. So, let's cover that next.

RESTful JSON API

In order to understand REST, let's first define HyperText Transfer Protocol (HTTP ). HTTP is the underlying protocol of the Internet that defines how messages are formatted and transmitted and how services should respond when using a variety of methods. These methods consist of four main verbs, such as GET, PUT, POST, and DELETE. In order to fully understand how HTTP methods function, let's first define REST.

Representation State Transfer (REST ) is a stateless protocol that accesses addressable resources through HTTP methods. Stateless means that each request contains all of the information necessary to completely understand and use the data in the request, and addressable resources means that you can access the object via a URL.

That might not mean a lot in itself, but, by putting all of these ideas together, it becomes a powerful concept. Let's illustrate the power of REST by looking at two examples:

Resource

GET

PUT

POST

DELETE

http://localhost/collection

Read a list of all of the items inside of collection

Update the Collection with another collection

Create a new collection

Delete the collection

http://localhost/collection/abc123

Read the details of the abc123 item inside of collection

Update the details of abc123 inside of collection

Create a new object abc123 inside of a collection

Delete abc123 from collection

By looking at the table, you can see that each resource is in the form of a URL. The first resource is collection, and the second resource is abc123, which lives inside of collection. Each of these resources responds differently when you pass different methods to them. This is the beauty of REST and HTTP working together.

Notice the bold words I used in the table: Read, Update, Create, and Delete. These words are actually, in themselves, another concept, and it, of course, has its own term; CRUD. The unflattering term CRUD stands for Create, Read, Update, and Delete and is a concept that REST uses to define what happens to a defined resource when an HTTP method is combined with a resource in the form of a URL. So, if you were to boil all of this down, you would come to the following diagram:

This diagram means:

  1. In order to CREATE a resource, you can use either the POST or PUT method
  2. In order READ a resource, you need to use the GET method
  3. In order to UPDATE a resource, you need to use the PUT method
  4. In order to DELETE a resource, you need to use the DELETE method

As you can see, this concept of CRUD makes it really clear to find out what method you need to use when you want to perform a specific action.

Now that we've looked at what REST means, let's move onto the term API , which means Application Programming Interface. While there are a lot of different use cases and concepts of APIs, an API is what we'll use to programmatically interact with CouchDB.

Now that we have defined all of the terms, the RESTful JSON API could be defined as follows: we have the ability to interact with CouchDB by issuing an HTTP request to the CouchDB API with a defined resource, HTTP method, and any additional data. Combining all of these things means that we are using REST. After CouchDB processes our REST request, it will return with a JSON-formatted response with the result of the request.

All of this background knowledge will start to make sense as we play with CouchDB's RESTful JSON API, by going through each of the HTTP methods, one at a time.

We will use curl to explore each of the HTTP methods by issuing raw HTTP requests.

Time for action – getting a list of all databases in CouchDB

Let's issue a GET request to access CouchDB and get a list of all of the databases on the server.

  1. Run the following command in Terminal

    curl -X GET http://localhost:5984/_all_dbs

  2. Terminal will respond with the following:

    ["_users"]

What just happened?

We used Terminal to trigger a GET request to CouchDB's RESTful JSON API. We used one of the options: -X, of curl, to define the HTTP method. In this instance, we used GET. GET is the default method, so technically you could omit -X if you wanted to. Once CouchDB processes the request, it sends back a list of the databases that are in the CouchDB server. Currently, there is only the _users database, which is a default database that CouchDB uses to authenticate users.

Time for action – creating new databases in CouchDB

In this exercise, we'll issue a PUT request , which will create a new database in CouchDB.

  1. Create a new database by running the following command in Terminal:

    curl -X PUT http://localhost:5984/test-db

  2. Terminal will respond with the following:

    {"ok":true}

  3. Try creating another database with the same name by running the following command in Terminal:

    curl -X PUT http://localhost:5984/test-db

  4. Terminal will respond with the following:

    {"error":"file_exists","reason":"The database could not be
    created, the file already exists."}

  5. Okay, that didn't work. So let's to try to create a database with a different name by running the following command in Terminal:

    curl -X PUT http://localhost:5984/another-db

  6. Terminal will respond with the following:

    {"ok":true}

  7. Let's check the details of the test-db database quickly and see more detailed information about it. To do that, run the following command in Terminal:

    curl -X GET http://localhost:5984/test-db

  8. Terminal will respond with something similar to this (I re-formatted mine for readability):

    {
    "committed_update_seq": 1,
    "compact_running": false,
    "db_name": "test-db",
    "disk_format_version": 5,
    "disk_size": 4182,
    "doc_count": 0,
    "doc_del_count": 0,
    "instance_start_time": "1308863484343052",
    "purge_seq": 0,
    "update_seq": 1
    }

What just happened?

We just used Terminal to trigger a PUT method to the created databases through CouchDB's RESTful JSON API, by passing test-db as the name of the database that we wanted to create at the end of the CouchDB root URL. When the database was successfully created, we received a message that everything went okay.

Next, we created a PUT request to create another database with the same name test-db. Because there can't be more than one database with the same name, we received an error message

We then used a PUT request to create a new database again, named another-db. When the database was successfully created, we received a message that everything went okay.

Finally, we issued a GET request to our test-db database to find out more information on the database. It's not important to know exactly what each of these statistics mean, but it's a useful way to get an overview of a database.

It's worth noting that the URL that was called in the final GET request was the same URL we called when we first created the database. The only difference is that we changed the HTTP method from PUT to GET. This is REST in action!

CouchDB and PHP Web Development Beginner's Guide Get your PHP application from conception to deployment by leveraging CouchDB's robust features with this book and ebook.
Published: June 2012
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Time for action — deleting a database In CouchDB

In this exercise, we'll call a DELETE request to delete the another-db database.

  1. Delete another-db by running the following command in Terminal:

    curl -X DELETE http://localhost:5984/another-db

  2. Terminal will respond with the following:

    {"ok":true}

What just happened?

We used Terminal to trigger a DELETE method to CouchDB's RESTful JSON API. We passed the name of the database that we wanted to delete, another-db, at the end of the root URL. When the database was successfully deleted, we received a message that everything went okay.

Time for action — creating a CouchDB document

In this exercise, we'll create a document by initiating a POST call. You'll notice that our curl statement will start to get a bit more complex./p>

  1. Create a document in the test-db database by running the following command in Terminal:

    curl -X POST -H "Content-Type:application/json" -d '{"type":
    "customer", "name":"Tim Juravich", "location":"Seattle, WA"}'
    http://localhost:5984/test-db

  2. Terminal will respond with something similar to the following:

    {"ok":true,"id":"39b1fe3cdcc7e7006694df91fb002082","rev":
    "1-8cf37e845c61cc239f0e98f8b7f56311"}

  3. Let's retrieve the newly created document from CouchDB. Start by copying the ID you were returned at the last response of the Terminal to your clipboard; mine is 39b1fe3cdcc7e7006694df91fb002082, but yours will be different. Then run this command in Terminal, pasting your ID at the end of the URL:

    curl -X GET http://localhost:5984/test-db/41198fc6e20d867525a8faeb
    7a000015 | python -mjson.tool

  4. Terminal will respond with something similar to the following:

    {
    "_id": "41198fc6e20d867525a8faeb7a000015",
    "_rev": "1-4cee6ca6966fcf1f8ea7980ba3b1805e",
    "location": "Seattle, WA",
    "name": "Tim Juravich",
    "type:": "customer"
    }

What just happened?

We used Terminal to trigger a POST call to CouchDB's RESTful JSON API. This time, our curl statement gained some more options that we haven't used before. The -H option enables us to set the header of the HTTP request for POST methods. We need to set the contenttype to JSON so that CouchDB's RESTful API knows what format is coming in. We also used a new option, -d option , which stands for data. The data option allows us to pass data in the form of a string along with our curl statement.

After creating our document, we retrieved it to Terminal by submitting a GET request to http://localhost:5984/test-db/41198fc6e20d867525a8faeb7a000015. In response, we received a JSON object containing all of the document's data. At the end of this request, we did something a little diff erent. We added python –mjson.tool, which is a built-in component from Python that enables us to nicely format our JSON responses, so that we can make more sense of them. This will come in handy as we start looking at more complex documents.

I know that t his has been a bit ti resome, but curl will be the main method that our PHP code will use to talk to CouchDB, so it's important that we're familiar with how it works. Luckily, there is an easier way to access and manage your data through a tool named Futon.

Futon

CouchDB comes with a built-in web-based administration console called Futon. Futon allows you to manage databases, users, and documents in a simple interface. The best part of Futon is that it's already installed and ready to go, since it comes packed with CouchDB.

Let's check it out:

  1. Open your browser.
  2. Go to http://localhost:5984/_utils/.

    This is Futon's Overview page. On this page, you can see all of the databases in the CouchDB installation and the ability to create new ones. You should see the database test-db that we created in the previous steps, and you can also see the _users database that is in the CouchDB installation by default.

  3. Let's dig further into our database test-db by clicking on the link for test-db in the database list on the Overview page.

    The page you see is the database detail. In this page, you can see a list of all of the documents that are in our database along with some actions that you can perform on the selected database such as New Document, Security, Compact & Cleanup…, Delete Database, Search, and so on. It's worth noting that Futon is just a helper, and all of these functions are available through curl as well.

  4. Let's dig deeper into Futon by clicking on on a document, and you'll be forwarded to the document detail.

    This data should look familiar! All of our keys are listed on the left , and the values are listed on the right

Time for action – updating a document in Futon

Using Futon, you can easily update the values of this document. Let's go through a quick example.

  1. Make sure you have the document open in your browser.
  2. Note the value of _rev in your document.
  3. Double-click the value of the location field: Seattle, WA, and change it to New York, NY.
  4. Click on Save Document at the top of the page.
  5. Check to make sure that the value of _rev in your document has changed, and that New York, NY is now the value of location.

What just happened?

You just used Futon to change the value of a field in our document and then saved changes to update the document. When the document refreshed, you should have noticed that the _rev field has changed, and your change to the field was updated.

You may have also noticed that Previous Version looks like it's clickable now. Click on it and see what happens. Futon displays the old version of the document with Seattle, WA in the location, as opposed to the new value of New York, NY.

You will now see CouchDB's revisions in full effect. If you want to, you can cycle through all of the versions of the document using the Previous Version and Next Version links.

There are two important things we need to note about CouchDB's revision system: You cannot update an old version of a document; if you try to save an old version of a document, CouchDB will return a document update confl ict error. This is because the only real version of the document is the most current one. Your revision history is only temporary. If your database kept a record of every single change, it would start to really get bloated. So, CouchDB has a feature called Compaction that will get rid of any of the old revisions.

Time for action – creating a document in Futon

We've gone through the updating of existing documents. Let's create a document from scratch in Futon.

  1. Go to the database overview by clicking on the database name, test-db, in the header
  2. Click on New Document
  3. A blank document is created and ready for us to put in new fields. Notice that the _id is already set for us (but we can change it if we want).
  4. Click on Add Field to create a new field, and call it location.
  5. Double-click on the value right next to the label that says null, and enter in your current location.
  6. Click on Add Field to create a new field, and call it name.
  7. Double-click on the value right next to the label that says null, and enter in your name.
  8. Click on Save Document at the top of the page.
  9. The document has been saved. Notice that it now has a _rev value set.

What just happened?

You just used Futon to create a document from scratch. When the document was first created, CouchDB created a unique ID for you to set it as the value of the _id field. Next, you added the name field and inputted your name as its value. Finally, you saved it to create a new document.

Security

Up to this point, we've created, read, updated, and deleted documents and databases, and we've done all of this without any type of security. When you don't have any administrators on your CouchDB instance, it's called Admin Party, and that simply means that CouchDB will process any request from anybody for anything.

CouchDB and PHP Web Development Beginner's Guide Get your PHP application from conception to deployment by leveraging CouchDB's robust features with this book and ebook.
Published: June 2012
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Time for action – taking CouchDB out of Admin Party

Having CouchDB unsecure isn't bad when you are programming locally, but it can be catastrophic if you accidentally have an unsecure database on a publicly accessible server. Let's briefly add security now to make sure you know how to do it in the future.

  1. Open Futon to the Overview, and look at the bott om right corner. You'll see text that says:

    Welcome to Admin Party!
    Everyone is admin. Fix this.

  2. Click on the Fix this link.
  3. A new window will pop up, prompting you Create Server Admin.

  4. Enter in a username and password that you want to use for your administrator account, and click on Create.

What just happened?

You just used Futon to add a server admin to your CouchDB installation. The Create Server Admin pop up said that once a server admin was added, you would be able to create anddestroy databases, and perform other administrative functions. All other users (including anonymous users) can still read and write to the databases. With that in mind, we'll want to add some security onto the database as well

Time for action – anonymously accessing the _users database

Let's go through a quick exercise of calling a curl statement to the _users database to see why it's important to secure our data.

  1. Open Terminal.
  2. Run the following command, replacing your_username with the username of the server admin that you just created.

    curl localhost:
    5984/_users/org.couchdb.user:your_username | python
    -mjson.tool

  3. Terminal will respond with something similar to:

    {
    "_id": "org.couchdb.user:your_username",
    "_rev": "1-b9af54a7cdc392c2c298591f0dcd81f3",
    "name": "your_username",
    "password_sha": "3bc7d6d86da6lfed6d4d82e1e4d1c3ca587aecc8",
    "roles": [],
    "salt": "9812acc4866acdec35c903f0cc072c1d",
    "type": "user"
    }

What just happened?

You used Terminal to create a curl request to read the document containing your server admin's data. The passwords in the database are encrypted, but it's possible that someone could still unencrypt the password or use the usernames of the users against them. With that in mind, let's secure the database so that only administrators can access this database.

Time for action – securing the _users database

Let's secure the _users database so that only server admins can read, write, and edit the other users within the system.

  1. Open Futon to the Overview.
  2. Click on the _users database.
  3. Click on Security at the top of the screen.

  4. Change the values of Roles for both Admins and Readers to ["admins"], so it looks as follows:

What just happened?

You just changed the roles of Admins and Readers for the _users database to ["admins"], so that only admins could read or alter the design documents and readers' list. We made the format of the roles ["admins"] because it accepts roles in the form of an array.

Time for action – checking to make sure the database is secure

Your _users database should be secure, so that only admins can read or alter the structure of the database. Let's quickly test this:

  1. Open Terminal.
  2. Try to read the user document again by running the following command. Again, replace your_username with the username of the service admin that you just created:

    curl localhost:5984/_users/org.couchdb.user:your_username

  3. Terminal will respond with the following:

    {"error":"unauthorized","reason":"You are not authorized
    to access this db."}

What just happened?

With the CouchDB instance out of Admin Party mode, the authentication module stepped in to make sure that anonymous users couldn't read the database.

This is one of the simplest ways to add security to a database.

If you were to play around with the command line again, you would be restricted by doing anything with the _users database, but you would also notice that the test-db databaseis operating just as it was before, perfect! That's exactly what we wanted. You might be asking how do I access the _users database through the command line, now that security is enabled? You have to show that you are an admin by passing your credentials to the RESTful JSON API.

Time for action – accessing a database with security enabled

Let's quickly try to access a database that has security enabled by passing the username and password with our request.

  1. Open Terminal.
  2. View all of the documents saved in the _users database by running the following command. Replace username and password with your admin's username and password.

    curl username:password@localhost:5984/_users/_all_docs

  3. Terminal will respond with the same data that you saw before you added the authentication.

    {
    "_id": "org.couchdb.user:your_username",
    "_rev": "1-b9af54a7cdc392c2c298591f0dcd81f3",
    "name": "your_username",
    "password_sha": "3bc7d6d86da6lfed6d4d82e1e4d1c3ca587aecc8",
    "roles": [],
    "salt": "9812acc4866acdec35c903f0cc072c1d",
    "type": "user"
    }

What just happened?

You just issued a GET request to the _users database and used the username and password of the server admin that we created earlier to authenticate us. Once authenticated, we were able to access the data normally. If you want to perform any action on a secure database, you just need to prepend username:password@ before the URL of the resource you would like to work with.

Summary

We learned a lot about CouchDB in this article. Let's quickly review:

  • We defined CouchDB by looking at databases, documents, and the RESTful JSON API
  • We compared CouchDB to a traditional relational database such as MySQL
  • We interacted with CouchDB's RESTful JSON API, using curl statements
  • We created and altered documents by using Futon
  • We learned how to add security to a database and tested its effectiveness

Resources for Article :


Further resources on this subject:


About the Author :


Tim Juravich

Tim Juravich is an experienced product, program, and technology leader that has spent nearly the past decade leading teams through a variety of projects in PHP, Ruby, and .NET. After gaining experience at several Fortune 500 companies, Tim discovered entrepreneurship, founded three of his own startups, and has helped dozens of other startups open their doors. Tim currently serves as the Director of Program Management for Thinktiv, a venture accelerator.

Books From Packt


PHP and MongoDB Web Development Beginner’s Guide
PHP and MongoDB Web Development Beginner’s Guide

RESTful PHP Web Services
RESTful PHP Web Services

Expert   PHP 5 Tools
Expert PHP 5 Tools

PHP   Team Development
PHP Team Development

PHP Web   2.0 Mashup Projects: Practical PHP Mashups with Google Maps, Flickr, Amazon, YouTube, MSN Search,   Yahoo!
PHP Web 2.0 Mashup Projects: Practical PHP Mashups with Google Maps, Flickr, Amazon, YouTube, MSN Search, Yahoo!

Smarty PHP Template Programming and Applications
Smarty PHP Template Programming and Applications

AJAX and PHP: Building Responsive Web Applications
AJAX and PHP: Building Responsive Web Applications

PHP Oracle Web Development: Data processing, Security, Caching, XML, Web Services, and Ajax
PHP Oracle Web Development: Data processing, Security, Caching, XML, Web Services, and Ajax


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
r
K
8
S
C
K
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software