December 26th 2008

Lisp, CouchDB and cl-couch example usage

Tags: couchdb lisp code

I have been reading up on CouchDB, an interesting alternative to using relational databases for (usually) completely the wrong purpose. After the last contract I have been working on and having to deal with the mess that led to I can really see the need for tools like this.

I always thought it was weird how you ended up having to do loads of queries per page viewed, how you are limited by SQL when doing anything more complex things and buggered when it came to storing tree’s or other structures. With CouchDB queries are prepared in advance using proper programing languages and are called views, this lets you grab stuff with a lot more power. Also interesting was the idea that you are not forced into a rigid structure for your data. (You can have a query that simple ignores records that aren’t relevant for example.)

A free online book, friendly IRC channel and a great Lisp library are some of the bonuses to what already looks like a pretty good idea.

Another really interesting part of CouchDB is that it gives you your data in JSON form so you can actually skip the ‘PHP Layer’ and make a dynamic application with just HTML, Javascript and CouchDB! (Just view the source of that page to see!)

I am going to write a couple of basic programs to get the hang of CouchDB soon but before I started I needed to get a few examples working. It took me a while so to save you the bother here is the code:

(asdf:oos 'asdf:load-op :cl-couch)

; Setup the blog package
(defpackage :blog
  (:use :asdf :asdf-install :cl :hunchentoot :cl-who :cl-couchdb-client)
  (:shadowing-import-from #:cl-couchdb-client #:url-encode :url-decode))
(in-package :blog)

; Connect to CouchDB

; Create a database
(couch-request :put (contacts))

; Add a few records
(couch-request :post (contacts) '(("Name" . "Simon")
                                  ("Skype" . "")))

(couch-request :post (contacts) '(("Name" . "Hozay Jones")
                                  ("Email" . "")
                                  ("Address" . "123 test st")))

(couch-request :post (contacts) '(("Name" . "Dave") ("Website" . "")))

(couch-request :post (contacts) '(("Crap" . "Blah")))

; List the records
(couch-request :get (contacts _all_docs))

; Now using futon create a view for the contacts database
; Here is the map javascript function to use:

;function(doc) {
;  if (doc.Name) {
;    emit(doc.Name, doc);
;  }

; Call the design document contacts and the view by_name

; Now we can use this view to see all the records with a Name
(couch-request :get (contacts/_view/contacts/by_name))

; And now any with the name Simon
(couch-request :get (contacts/_view/contacts/by_name :key "\"Simon\""))

(I am brand new to this so I might have done some bits in a stupid way, it does give you somewhere to start from though.)

Any feedback would be great,

Cheers, Dave.