<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Probably Programming &#187; CouchDB</title>
	<atom:link href="http://probablyprogramming.com/tag/couchdb/feed/" rel="self" type="application/rss+xml" />
	<link>http://probablyprogramming.com</link>
	<description>It&#039;s what I&#039;m doing, and what posts on this blog are about.</description>
	<lastBuildDate>Wed, 10 Feb 2010 02:03:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Storing Hierarchical Data in CouchDB</title>
		<link>http://probablyprogramming.com/2008/07/04/storing-hierarchical-data-in-couchdb/</link>
		<comments>http://probablyprogramming.com/2008/07/04/storing-hierarchical-data-in-couchdb/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 23:20:52 +0000</pubDate>
		<dc:creator>pib</dc:creator>
				<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Database]]></category>

		<guid isPermaLink="false">http://probablyprogramming.com/?p=81</guid>
		<description><![CDATA[Much to my surprise, my last post generated more traffic in a single day than my blog has ever gotten in a single month. Apparently people are quite interested in making web applications with Python. I&#8217;ve started on part two, but since so many people showed interest I want to spend more time on it [...]]]></description>
			<content:encoded><![CDATA[<p>Much to my surprise, my last post generated more traffic in a single day than my blog has ever gotten in a single month. Apparently people are quite interested in making web applications with Python. I&#8217;ve started on part two, but since so many people showed interest I want to spend more time on it than I spent on the last one. So instead, you get this post.</p>

<p>So I&#8217;ve been fiddling around with CouchDB lately. Since it&#8217;s common to store tree-based data, and it&#8217;s kind of a pain to do so in your standard relational DB, I thought it would be a good exercise to see how hard it is to store hierarchical data in CouchDB.</p>

<p>Turns out it&#8217;s pretty easy.</p>

<p><span id="more-81"></span></p>

<p>For comparison, you might want to check out <a href="http://www.sitepoint.com/article/hierarchical-data-database">this article</a> on storing trees in a relational database. It covers how to store tree-like data using both Adjacency Lists and Modified Preorder Tree Traversal (that&#8217;s a mouthful). I&#8217;ll cover how I put the data into CouchDB and some of the ways you might want to pull it out.</p>

<h3>Storing the Tree</h3>

<p>Rather than keeping track of parents as in the Adjacency List method or &#8216;left&#8217; and &#8216;right&#8217; as in the Modified Preorder Tree Traversal method, I store the full path to each node as an attribute in that node&#8217;s document. I then use this data in the views to organize the data as I need it.</p>

<p>The test data I used is as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#91;</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span>   <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #339933;">,</span>  <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Red&quot;</span><span style="color: #339933;">,</span>    <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Red&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Cherry&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Red&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Cherry&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Tomato&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Red&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Tomato&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Yellow&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Yellow&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Banana&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Fruit&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Yellow&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Banana&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Meat&quot;</span><span style="color: #339933;">,</span>   <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Meat&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Beef&quot;</span><span style="color: #339933;">,</span>   <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Meat&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Beef&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;_id&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;Pork&quot;</span><span style="color: #339933;">,</span>   <span style="color: #3366CC;">&quot;path&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;Food&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Meat&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;Pork&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#93;</span></pre></div></div>


<p>In a real system you&#8217;d probably want to use some sort of UUID instead of descriptive strings, since conflicts between node names could be bad. In fact, it&#8217;d probably be much faster to just use numbers, since comparisons on numbers are generally much faster. For the purposes of this post, however, it&#8217;s much easier to understand if it&#8217;s descriptive text.</p>

<p>Once that data is in your DB, it&#8217;s time to get it out again!</p>

<h3>Retrieving the whole tree</h3>

<p>The CouchDB map function to retrieve the whole tree is nice and simple:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>doc<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    emit<span style="color: #009900;">&#40;</span>doc.<span style="color: #660066;">path</span><span style="color: #339933;">,</span> doc<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Using the path as the key, the documents will be sorted as above, with each parent immediately followed by its children.</p>

<p>One option to get the data into an actual tree would be to add a reduce function to the view:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>keys<span style="color: #339933;">,</span> vals<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    tree <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> vals<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        current <span style="color: #339933;">=</span> tree<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> j <span style="color: #000066; font-weight: bold;">in</span> vals<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">path</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            child <span style="color: #339933;">=</span> vals<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">path</span><span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>current<span style="color: #009900;">&#91;</span>child<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> undefined<span style="color: #009900;">&#41;</span> 
                current<span style="color: #009900;">&#91;</span>child<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
            current <span style="color: #339933;">=</span> current<span style="color: #009900;">&#91;</span>child<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> 
        current<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_data'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> vals<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066; font-weight: bold;">return</span> tree<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p><em>Note: don&#8217;t use this reduce function, since it doesn&#8217;t take the rereduce parameter into account, and would most likely not work correctly if a rereduce was done.</em></p>

<p>I chose to write a similar function in Python and use that to generate my tree on the client side:</p>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> TreeNode<span style="color: black;">&#40;</span><span style="color: #008000;">dict</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> tree_from_rows<span style="color: black;">&#40;</span><span style="color: #008000;">list</span><span style="color: black;">&#41;</span>:
    tree = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> item <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">list</span>:
        current = tree
        <span style="color: #ff7700;font-weight:bold;">for</span> child <span style="color: #ff7700;font-weight:bold;">in</span> item.<span style="color: black;">value</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'path'</span><span style="color: black;">&#93;</span>:
            current = current.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>child, TreeNode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        current.<span style="color: black;">data</span> = item.<span style="color: black;">value</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> tree</pre></div></div>


<p>This code does the job nicely and allows me to use the same function to build a tree from several different views without duplicating code.</p>

<h3>Getting a subtree</h3>

<p>To get all the nodes which are underneath a specific node, I implemented the view&#8217;s reduce function as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>doc<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> doc.<span style="color: #660066;">path</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
        emit<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>doc.<span style="color: #660066;">path</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> doc.<span style="color: #660066;">path</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> doc<span style="color: #009900;">&#41;</span> 
    <span style="color: #009900;">&#125;</span> 
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Again, this is pretty simple. The only difference from the last view is that I can now query this view with a startkey and endkey (see the <a href="http://wiki.apache.org/couchdb/HttpViewApi#head-45806c14f9b1a9e1a4b0ea579ffdf150077f8cb9">CouchDB HttpViewApi</a>) to get only nodes under a certain node. I could actually do that with the previous view, except I&#8217;d have to include the full path to the node in my startkey, which is a bit too much.</p>

<p>For example, if you had CouchDB running on your machine right now with my example data loaded and went to <a href="http://localhost:5984/tree/_view/tree/descendants?startkey=[%22Fruit%22]&amp;endkey=[%22Fruit%22,{}]">http://localhost:5984/tree/_view/tree/descendants?startkey=["Fruit"]&amp;endkey=["Fruit",{}]</a></p>

<h3>How Many Descendants</h3>

<p>Getting the number of descendants for a given node is simple. The view is as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #3366CC;">'descendant_count'</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">'map'</span><span style="color: #339933;">:</span>    <span style="color: #3366CC;">'function(doc) { for (var i in doc.path) { emit(doc.path[i], 1) } }'</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">'reduce'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'function(keys, values) { return sum(values) }'</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>This will count the parent node as well, so you will probably want to subtract one from it at some point. To use this view simply call it with the key parameter set to the id of the desired root node.</p>

<h3>Getting the immediate children of a node</h3>

<p>Sometimes you just want to get a list of nodes which are immediately under a given node. This can be done by using a map with the following map function:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>doc<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
    emit<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>doc.<span style="color: #660066;">path</span>.<span style="color: #660066;">slice</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,-</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> doc.<span style="color: #660066;">path</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> doc<span style="color: #009900;">&#41;</span> 
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>This map function simply takes the second-to-last element from the path and uses that as the first element in the key. You can query this view in the same way as the &#8220;getting a subtree&#8221; view above.</p>

<h3>Adding a node</h3>

<p>Adding a node to the tree is fairly simple. Set the new node&#8217;s path to be the path of the desired parent node with the new node&#8217;s ID appended to the end. That&#8217;s it.</p>

<h3>Deleting a node</h3>

<p>Deleting a node is a bit trickier since any given node may have some number of children. You can get the list of nodes in the subtree as outlined above and then do a bulk update to delete each of them.</p>

<p>Depending on the data being stored, deleting the whole sub-tree might not ever be something you want to do, in a discussion forum, for example, you might want to simply delete a single offensive post, leaving any replies which might have been posted. Even in this case, it&#8217;s more likely that you&#8217;d want to set a flag indicating the deletion rather than actually deleting the post.</p>

<h3>Moving a node to another parent</h3>

<p>This is an instance where being able to update just certain fields in a document would be handly, since bulk-updating a large chunk of documents could start to kill performance.</p>

<p>Either way, if something needs to be reparented, it&#8217;s just a matter of getting all nodes which are children of a certain node, then doing a bulk update to change their paths to wherever they need to be.</p>

<p>This part worries me a bit, because there&#8217;s a chance that somebody else could add a new child node while you are in the process of moving the sub-tree, leaving that new node dangling by itself in a sub-tree which no longer exists. I&#8217;m not sure of the best approach to avoid such a problem.</p>

<h3>Conclusion</h3>

<p>After my initial experimentation, it seems that CouchDB could potentially do a good job handling hierarchical data. It&#8217;s simpler to understand and implement than Modified Preorder Tree Traversal, but still has the advantage of being able to get a whole tree in a single query, unlike the Adjacency List model.</p>

<p>I wrote some python code to load in my test data and query the various views I created. It requires <a href="http://code.google.com/p/couchdb-python/">CouchDB-Python</a>, which can be gotten via that link or from EasyInstall by running <em>easy_install CouchDB</em>.</p>

<p>My code can be found in the <a href="http://git.paulbonser.com/?p=couchdb.git;a=summary">appropriate spot</a> on my Gitweb.</p>

<div class="pitch">
Have some questions? Have an idea for a better way of storing hierarchical data in CouchDB? Any other comments? Then leave a comment below!
</div>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fprobablyprogramming.com%2F2008%2F07%2F04%2Fstoring-hierarchical-data-in-couchdb%2F';
  addthis_title  = 'Storing+Hierarchical+Data+in+CouchDB';
  addthis_pub    = 'misterpib';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://probablyprogramming.com/2008/07/04/storing-hierarchical-data-in-couchdb/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>CouchDB looks Awesome, my Slug is borked</title>
		<link>http://probablyprogramming.com/2008/06/24/couchdb-looks-awesome-my-slug-is-borked/</link>
		<comments>http://probablyprogramming.com/2008/06/24/couchdb-looks-awesome-my-slug-is-borked/#comments</comments>
		<pubDate>Wed, 25 Jun 2008 04:28:00 +0000</pubDate>
		<dc:creator>pib</dc:creator>
				<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[nslu2]]></category>
		<category><![CDATA[slug]]></category>

		<guid isPermaLink="false">http://probablyprogramming.com/?p=79</guid>
		<description><![CDATA[In lieu of a real blog post, and as a way to break the 3-week silence that has recently hung over this blog, I&#8217;d just like to say this:

I&#8217;ve been looking at CouchDB, and it looks awesome.

For those who don&#8217;t know, CouchDB is a RESTful, distributed, schema-free, document-oriented database.

It looks like it&#8217;s the answer to [...]]]></description>
			<content:encoded><![CDATA[<p>In lieu of a real blog post, and as a way to break the 3-week silence that has recently hung over this blog, I&#8217;d just like to say this:</p>

<p>I&#8217;ve been looking at <a href="http://incubator.apache.org/couchdb/">CouchDB</a>, and it looks <em>awesome</em>.</p>

<p>For those who don&#8217;t know, CouchDB is a <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful</a>, distributed, schema-free, <a href="http://en.wikipedia.org/wiki/Document-oriented_database">document-oriented database</a>.</p>

<p>It looks like it&#8217;s the answer to all those times when I was thinking to myself &#8220;Man, this really doesn&#8217;t need a relational database, it needs&#8230;something else.&#8221;</p>

<p>Well, from what I&#8217;ve seen so far, this just might be the something else.</p>

<p>I would have more to say about it, some examples even, except I&#8217;ve spent my last two evenings fiddling with my <a href="http://probablyprogramming.com/2008/04/06/nslu2-almost-set-up/">NSLU2</a>, trying to get it actually up and working after having several hard drive issues. I&#8217;ve given up on one of my hard drives, but now the Debian install won&#8217;t finish, it dies half way through saying it failed to finish the configuration or some such thing.</p>

<p>Anyway, I may just have to give up on it sooner or later and start doing more interesting things, and once I do that, I&#8217;ll have something more to say about CouchDB, with some example code even.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fprobablyprogramming.com%2F2008%2F06%2F24%2Fcouchdb-looks-awesome-my-slug-is-borked%2F';
  addthis_title  = 'CouchDB+looks+Awesome%2C+my+Slug+is+borked';
  addthis_pub    = 'misterpib';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>
]]></content:encoded>
			<wfw:commentRss>http://probablyprogramming.com/2008/06/24/couchdb-looks-awesome-my-slug-is-borked/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
