Pour une raison que j’expliquerai dans un prochain billet, je m’intéresse actuellement à CouchDB.
Il s’agit d’un serveur de base de données orienté document.

Plus clairement, chaque serveur va avoir plusieurs bases.
Et chacunes de ces bases va avoir plusieurs documents. Chaque document pourra avoir un ou plusieurs champs et ces champs pourront varier en fonction du document.

Du coup pour une base « fichiers » par exemple, vous pourrez avoir un document qui représente une image et qui aura les champs « nom », « tumbnail » et « size ».
Et un document représentant un fichier texte et qui aura uniquement les champs « nom » et « size ». Chaque document ne possède que les champs dont il a besoin.

Pour l’installation du serveur, je vous invite à vous référer à la documentation officielle.
Une fois que cela est fait, passons à la suite de cet article.

CouchDB implémente un serveur HTTP acceptant des requêtes JSON. Mettons en place une librairie Ruby simple permettant de faire ces appels (et honteusement récupérée de la documentation CouchDB officielle).

require 'net/http'
module Couch
    class Server
        def initialize(host, port, options = nil)
            @host = host;
            @port = port;
            @options = options;
        end

        def delete(uri)
            request(Net::HTTP::Delete.new(uri))
        end

        def get(uri)
            request(Net::HTTP::Get.new(uri))
        end

        def put(uri, json)
            req = Net::HTTP::Put.new(uri)
            req["content-type"] = "application/json"
            req.body = json
            request(req)
        end

        def post(uri, json)
            req = Net::HTTP::Post.new(uri)
            req["content-type"] = "application/json"
            req.body = json
            request(req)
        end

        def request(req)
            res = Net::HTTP.start(@host, @port) {|http|
                http.request(req)
            }
            handle_error(req, res) if (not res.kind_of?(Net::HTTPSuccess))
            res
        end

        private
        def handle_error(req, res)
            e = RuntimeError.new("#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}")
            raise e
        end
    end
end

Nous implémentons une méthode pour chacune des actions faisables avec tout serveur de base de données : listage des données, ajout d’un nouveau document, modification d’un document et suppression de celui-ci.

Utilisons cette librairie.

require 'json'
require 'digest/md5'

# Connexion au serveur
server = Couch::Server.new("localhost", "5984")

# Création de la base "foo"
server.put("/foo/", "")

# Ajout d'un document
doc = Hash.new(:name => 'Document Name', :content => 'The Content')
id = Digest::MD5.hexdigest(doc[:name] + '/' + doc[:content])
server.put("/foo/#{id}", doc.to_json)

# Lecture du document créé
p JSON.Parse(server.get("/foo/#{id}").body)

Détaillons ce que nous faisons.

server = Couch::Server.new("localhost", "5984")

Pour commencer, nous instancions la librairie CouchDB en précisant l’adresse du serveur et son port.

server.put("/foo/", "")

Puis nous créons une base de données nommée « foo ».
Une requête « PUT » sur l’url de la nouvelle base crée celle-ci.

doc = Hash.new(:name => 'Document Name', :content => 'The Content')
id = Digest::MD5.hexdigest(doc[:name] + '/' + doc[:content])
server.put("/foo/#{id}", doc.to_json)

Ici cela devient plus intéressant.

Nous commençons par créer un hash contenant tous les champs qui constitueront le document.
Puis nous définissons l’identifiant de ce document.

Nous définissons celui-ci en une chaine md5 et non pas un simple entier.
En effet si vous faites de la réplication de bases, vous risquez d’avoir des duplicats d’identifiants en se contentant d’un identifiant.
Ici avec une chaine md5 contenant le contenu originel du document, il y a extrêmement peu de chances que nous ayons des duplicats.

Puis nous transmettons une requête permettant de créer le document ayant l’identifiant que nous venons d’attribuer avec le contenu donné.

p JSON.Parse(server.get("/foo/#{id}").body)

Pour finir nous lisons le contenu du document que nous venons de créer.
Une requête GET sur l’url du document permet d’en retourner le contenu au format JSON, que nous parsons grâce à la librairie JSON Ruby. Il ne nous reste plus qu’à afficher le contenu de la manière dont nous le désirons.

Bien évidemment il existe de multiples librairies bien plus évoluées que ce que nous venons de faire.
Par exemple CouchREST, ActiveCouch ou RelaxDB.
Mais nous avons vu dans cet article les bases de l’utilisation de CouchDB et son fonctionnement. A vous de lire la documentation de ces projets si vous désirez les utiliser :)

2 Réponses à “Première introduction à CouchDB”

  1. segle dit :

    Je suis aussi intéressé par les BDD orientées documents.

    J’ai aussi jeté un oeil sur MongoDB (et la lib python quivabien).

    Ça promet beaucoup pour certaines utilisations très particulières où un BDD relationnelle n’est pas le plus adéquat.

    J’ai hâte de voir ce que tu prépares et quelle est la raison (le projet, sûrement) qui t’a poussé à t’intéresser à CouchDB :)

  2. Damien dit :

    J’ai beaucoup entendu parler de MongoDB (par shingara principalement).
    Sur ce projet je n’ai pas eu le choix de la base. Mais ça promet d’être particulièrement intéressant :p

    Plus d’infos vendredi ;)

Laisser une réponse

 
Fork me on GitHub