I’ve been developing a small app that should be a good fit for CouchDB. It’s a small app that will allow me to keep a series of notes, some of which are plain text and some are formatted in particular ways. The data needs to be shared between a number of devices with the ability to be edited on any of them – online and offline. It’s not a hugely complex app nor is it a unique problem, but it’s useful place to keep looking at CouchDB.

Why do I think CouchDB is a good fit? It’s NoSQL foundations means that data can be easily arranged and stored in ways that make sense for each type. The replication features will allow the various devices to sync with each other without any extra effort. Thanks to the Android Couchbase project it’s possible to use CouchDB on Android (albeit with a larger binary than I would like) allowing for offline storage.

As I’ll be using multiple devices, I’ve decided to start by letting the server allocate it’s default random _id which should avoid duplicates and not require me to devise some more complex scheme.

With a conventional SQL database the decision of how to arrange the data would be simple – a series of tables connected with joins. However, when contemplating how to arrange the data with NoSQL there doesn’t seem to be as simple a solution. This could be my inexperience with them but having read a lot of articles I think it’s just there are so many possible ways of arranging the data that the right solution will depend on the situation.

I’m keen to keep the complexity down but at the same time I don’t want to have a simpler database at the expense of making the interface more complex to work with. My original thought was to store all the related documents in an array embedded within a single document, for example

{<br></br>
"_id": "12345",<br></br>
"title": "Some Subject"<br></br>
"notes": [<br></br>
{<br></br>
"type": "text",<br></br>
"content": "Simple text note"<br></br>
},<br></br>
{<br></br>
"type": "text",<br></br>
"content": "Another simple piece of text"<br></br>
}<br></br>
]}<br></br>```

This is nice and simple and allows me to use a single request to get the entire document, but it adds a lot of complexity to the interface. When editing one of the notes, I would need to

1. request the document
2. edit the document
3. update the entire document

Far simpler from an editing point of view would be to have the notes as seperate records with a link back to their parent document. For example,

{


"_id": "12345",


"title": "Some Subject"


}


{


"_id": "23456",


"parent": "12345",


"type": "text",


"content": "Simple text note"


}


{


"_id": "34567",


"parent": "12345",


"type": "text",


"content": "Another simple piece of text"


}

```

This allows me to edit each document separately and so avoids the need to request the entire parent document and then manipulate the returned data prior to updating, but does raise the question of how I could efficiently request the document and all it’s related child documents. With some simple changes, a complex key in a view and careful use of parameters it turns out to be very possible.

First I alter the documents slightly by adding a type field to every document.

{<br></br>
"_id": "12345",<br></br>
"title": "Some Subject",<br></br>
"type": "subject"<br></br>
}<br></br>
{<br></br>
"_id": "23456",<br></br>
"parent": "12345",<br></br>
"type": "subject:note",<br></br>
"content-type": "text",<br></br>
"content": "Simple text note"<br></br>
}<br></br>
{<br></br>
"_id": "34567",<br></br>
"parent": "12345",<br></br>
"type": "subject:note",<br></br>
"content-type": "text",<br></br>
"content": "Another simple piece of text"<br></br>
}<br></br>```

Next I write a simple view function.




function(doc) {


if (doc.type) {


if (doc.type == "subject") {


emit([doc._id, 0], doc);


} else if (doc.type == "subject:note" && doc.topic) {


emit([doc.topic, 1], doc);


}


}


}```

Running this query (without any parameters) produces the following result,

<br></br>
{"total_rows": 3, "offset": 0, "rows": [<br></br>
{<br></br>
"id": "12345",<br></br>
"key": ["12345", 0],<br></br>
"value": {...}<br></br>
}, {<br></br>
"id": "23456",<br></br>
"key": ["12345", 1],<br></br>
"value": {...}<br></br>
}, {<br></br>
"id": "34567",<br></br>
"key": ["12345", 1],<br></br>
"value": {...}<br></br>
}<br></br>
]}<br></br>```

The ‘…’ in the value fields will have the contents of the document, so this query returns me all the information I need. Filtering is also possible thanks to CouchDB and the usual key, startkey and endkey parameters. Additionally I can add fields to the complex key without changing how it functions. Nice.

Getting a single subject with all the related notes is as simple as requesting the view with the parameters `?startkey=["12345"]&endkey;=["12345", 2]`.

If I add additional document types then I can simply adjust my view and return them as well, using the number to differentiate between them. Parsing the data for an interface becomes simple and each document can be edited/updated in isolation.