CouchDB : êtes-vous prêt pour le Couch Wide Web ?

GNU/Linux Magazine n° 124 | février 2010 | Michael Bailly.
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Deezer, Gmail, Google Docs, Facebook, ... Les applications web récentes n'ont plus grand chose en commun avec les pages web du vingtième siècle. La communauté CouchDB propose d'aller encore plus loin. Dans quelle direction, et par quels moyens ?

1. Introduction

CouchDB est le fer de lance des nouvelles générations de bases de données, dites « NoSQL ». On y stocke des données (documents) non structurées, que l'on peut mettre à jour et effacer. Finies les requêtes SQL de sélection par critères : elles sont remplacées par des vues, générées selon l'algorithme map-reduce. Le tout en utilisant le protocole HTTP, le format de données JSON, et Javascript comme langage de programmation des vues. Pas mal ? Ce n'est que le début ! CouchDB sait faire bien plus !

2. CouchDB sait stocker des fichiers

Il est possible de stocker des fichiers à l'intérieur des documents CouchDB. La manière la plus simple de stocker un fichier dans un document est d'utiliser la méthode PUT. Dans cet exemple, après avoir créé un document vide nommé doc1, on attache un fichier image.jpg, qui s'appellera logo.jpg dans le document.

### Je crée un document

$ curl -X PUT -d '{}' http://localhost:5984/example/doc1

{"ok":true,"id":"doc1","rev":"1-967a00dff5e02add41819138abb3284d"}

### j'attache le fichier image.jpg en tant que logo.jpg dans le document doc1

$ curl -X PUT -d @image.jpg -H 'Content-type: image/jpeg' \

http://localhost:5984/example/doc1/logo.jpg?rev=1-967a00dff5e02add41819138abb3284d

{"ok":true,"id":"doc1","rev":"2-481bb75e72e5414cbc275031fa8ad41a"}

Maintenant, lorsqu'on demande au serveur de nous retourner le document, on obtient :

{

    "_id":"doc1",

    "_rev":"2-481bb75e72e5414cbc275031fa8ad41a",

    "_attachments":

    {

        "logo.jpg":

        {

            "stub":true,

"content_type":"image/jpeg",

            "length":10089,

            "revpos":2

        }

    }

}

CouchDB a créé une clé _attachments dans le document doc1. Cet objet contient une clé logo.jpg (le nom de l'attachement), un mot-clé stub=true qui signifie que le contenu de l'attachement n'est pas dans cet objet JSON, mais seulement les métadonnées. On a aussi accès à la taille de la pièce jointe.

Comment diable peut-on récupérer ce fichier ? Simplement par son URL, avec la méthode GET :

$ curl -X GET http://localhost:5984/example/doc1/logo.jpg

Pour effacer le fichier attaché, on utilise la méthode DELETE, en passant en argument rev la dernière révision du document :

$ curl -X DELETE \

http://localhost:5984/example/doc1/logo.jpg?rev=2-481bb75e72e5414cbc275031fa8ad41a

3. CouchDB sait contrôler le format de sortie d'une requête

Le langage de base entre CouchDB et l'application cliente est JSON. Ceci n'est pas une limitation CouchDB : les méthodes show et list permettent toutes les fantaisies.

Pour illustrer ces fonctionnalités, stockons dans notre base de données example deux documents de type contact :

{

    'id': 'contact12',

    'type':'contact',

    'nom': 'Berners-Lee',

'prenom': 'Tim',

    'naissance': '8 Juin 1955'

}

{

    'id': 'contact13',

    'type':'contact',

    'nom': 'Lefebvre',

'prenom': 'Frederic',

    'naissance': '14 Octobre 1963'

}

Traduction en geek :

$ curl -X PUT -d '{"type":"contact","nom":"Berners-Lee","prenom":"Tim","naissance":"8 Juin 1955"}' http://localhost:5984/example/contact12

{"ok":true,"id":"contact12","rev":"1-3678fef53f1e14d8f325bdba29d939ec"}

$ curl -X PUT -d '{"type":"contact","nom":"Levebvre","prenom":"Frederic","naissance":"14 Octobre 1963"}' http://localhost:5984/example/contact13

{"ok":true,"id":"contact13","rev":"1-1b10e41515f72e5dbc176565c4f56d06"}

4. CouchDB sait contrôler le format de sortie d'un document

Une méthode show prend deux arguments : le document à traiter et des informations sur la requête HTTP. Le premier argument peut être nul, auquel cas le document spécifié dans l'URL est introuvable. Nous parlerons du deuxième argument bientôt.

La méthode show doit retourner un objet JSON, comprenant soit une clé body, donnant le texte à envoyer au navigateur, soit une clé json, contenant l'objet JSON à retourner au navigateur. De plus, cet objet peut aussi contenir une clé code permettant de contrôler le status code HTTP retourné (vous savez, 200, 404, ...). On peut aussi spécifier des headers HTTP spécifiques à inclure dans la réponse en déclarant un objet headers.

Dans notre simple exemple, on définit deux méthodes show : une full et une light dans un design document contacts :

{

    "_id": "_design/contacts",

    "language": "javascript",

    "shows" :

    {

        "light" : "function (doc, req) {

                            if ( !doc ) {

                                return { 'code': 404, 'body': 'Not found' };

                            }

                            return {

                                'body': '<span>'+doc.prenom+' '+doc.nom+'</span>'

                            };

                        }",

        "full" : "function (doc, req) {

                            if ( !doc ) {

                                return { 'code': 404, 'body': 'Not found' };

                            }

                            var back = '<div><h3>'+doc.prenom+' '+doc.nom+'</h3>';

back+='<p>Date de naissance : '+doc.naissance+'</p></div>';

                            return {'body': back};

}"

        }

}

En ayant assez de la ligne de commandes et des problèmes de quotes, j'utilise l'extension FireFox Poster afin d'envoyer la requête :

Poster affiche la réponse du serveur dans une fenêtre claire :

Comment utiliser les méthodes show maintenant ? L'URL dans ce cas est composée de la façon suivante :

http://[serveur]/[base de données]/[nom du design documents]/_show/[méthode show]/[id du document]

C'est parti :

$ curl http://localhost:5984/example/_design/contacts/_show/light/contact12

<span>Tim Berners-Lee</span>

$ curl http://localhost:5984/example/_design/contacts/_show/full/contact12

<div><h3>Tim Berners-Lee</h3><p>Date de naissance : 8 Juin 1955</p></div>

5. CouchDB sait contrôler le format d'une liste de documents

Pour affecter le format de sortie d'un document, on utilise les méthodes show. Pour affecter le format de sortie d'une liste de documents, obtenus en interrogeant une vue, on utilise les méthodes list. La syntaxe des méthodes list a changé récemment, ce qui suit est valide pour CouchDB >= 0.10.

Nous allons avoir besoin d'une vue by-name, appartenant au design document contacts, et qui renvoie les contacts stockés, ordonnés par nom (puis par prénom). Cela donne :

function (doc) {

  if ( doc.type && doc.type == 'contact' ) {

    emit( [doc.nom, doc.prenom] , null );

  }

}

Cette vue renvoie, avec les deux contacts que notre base contient :

{

    "total_rows":2,

    "offset":0,

    "rows":

    [

        {"id":"contact12","key":["Berners-Lee","Tim"],"value":null},

        {"id":"contact13","key":["Levebvre","Frederic"],"value":null}

]

}

Il faut maintenant créer une méthode de type list. Celle-ci prend deux arguments : head, qui correspond à de succinctes informations sur la vue en traitement (typiquement du style : {total_rows:2, offset:0}) et request, qui contient des informations sur la requête HTTP. Nous en parlerons juste après.

Les méthodes list ont à leur disposition des fonctions d'aide :

  • getRow() : permet d'obtenir le document suivant. C'est la plus importante.
  • send() : permet d'envoyer une partie du contenu.
  • start() : permet de définir des headers supplémentaires à envoyer.

Chaque appel à la fonction getRow() retourne la ligne suivante de la vue utilisée, sous forme d'objet JSON. Lorsque toutes les lignes ont été retournées, cette fonction renvoie null.

Le premier appel à getRow() renverra donc l'objet :

{"id":"contact12","key":["Berners-Lee","Tim"],"value":null}

Le second appel :

{"id":"contact13","key":["Levebvre","Frederic"],"value":null}

et les appels suivants renverront null.

Voici une fonction list qui renvoie les contacts en HTML :

function (head,req) {

    send("<ul>");

    var row = null;

    while ( row = getRow() ) {

       send("<li rel=\""+row.id+"\">"+row.key.join(', ')+"</li>");

}

    return "</ul>";

}

Dans le design document, nous créons une liste « html » qui contient la fonction précédente. Le document _design/contacts ressemble alors à :

{

    "_id":"_design/contacts",

"_rev":"5-77ed862cc4eb6e2523571bd5e91c5535",

    "language":"javascript",

    "shows":{

        "light":"function (doc, req) { if ( !doc ) { return { 'code': 404, 'body': 'Not found' }; } return { 'body': '<span>'+doc.prenom+' '+doc.nom+'</span>' }; }",

        "full":"function (doc, req) { if ( !doc ) { return { 'code': 404, 'body': 'Not found' }; } var back = '<div><h3>'+doc.prenom+' '+doc.nom+'</h3>'; back+='<p>Date de naissance : '+doc.naissance+'</p></div>'; return {'body': back}; }"

},

    "views":{

        "by-name":{

            "map":"function (doc) {\n if ( doc.type && doc.type == 'contact' ) {\n    emit( [doc.nom, doc.prenom] , null );\n }\n}"

        }

    },

    "lists":

    {

            "html":"function(head,req) {     send(\"<ul>\");     var row = null; while ( row = getRow() ) {        send(\"<li rel=\\\"\"+row.id+\"\\\">\"+row.key.join(', ')+\"</li>\");     } return \"</ul>\"; }"

}

}

L'URL d'appel d'une méthode list est composée de la façon suivante :

http://[serveur]/[base de donnees]/[nom du design documents]/_list/[methode list]/[nom de la vue]

Dans le cas présent :

http://localhost:5984/example/_design/contacts/_list/html/by-name

Et cette liste nous renvoie :

$ curl http://localhost:5984/example/_design/contacts/_list/html/by-name

<ul><li rel="contact12">Berners-Lee, Tim</li><li rel="contact13">Levebvre, Frederic</li></ul>

Il est bien entendu possible d'utiliser les paramètres de requête des vues dans cet URL. Par exemple, pour inverser l'ordre de tri :

$ curl http://localhost:5984/example/_design/contacts/_list/html/by-name?descending=true

<ul><li rel="contact13">Levebvre, Frederic</li><li rel="contact12">Berners-Lee, Tim</li></ul>

6. Les paramètres de requête

Dans les méthodes show et list, le second paramètre passé est un objet, qui contient quantité d'informations sur la requête en cours.

Le premier attribut de cet objet est info, et il contient les informations sur la base de données en cours, par exemple :

{

"db_name": "example",

"doc_count": 11,

"doc_del_count": 0,

"update_seq": 11,

"purge_seq": 0,

"compact_running": false,

"disk_size": 4930,

"instance_start_time": "1250046852598425",

"disk_format_version": 4

}

Le second attribut est verb, et donne le type de requête HTTP utilisée par le client : GET, POST, ...

Le troisième argument se nomme path, c'est un tableau contenant le chemin jusqu'à la méthode list ou show en cours :

["example","_design","lists","_list","html","by-name"]

L'attribut suivant est query et contient, si présents, les paramètres de requête :

{ "descending": true }

On peut aussi accéder aux headers HTTP envoyés par le client grâce à l'attribut headers :

{

  "Accept": "text/html,application/xhtml+xml ,application/xml;q=0.9,*/*;q=0.8",

  "Cookie": "_x=95252s.sd25; AuthSession=","Host": "127.0.0.1:5984",

...

}

Si la requête est de type POST, on dispose aussi des attributs body et form correspondant respectivement aux données postées en brut, et décodées en JSON.

Pourquoi est-ce si sympathique ? Et bien, on peut ajouter des paramètres de requête personnalisés (exemple : http://localhost:5984/example/_design/contacts/_list/html/by-name?neAvant=1960 ). Les shows et lists sont mis en cache, avec un hashtag dépendant des paramètres de requête.

Ce petit scénario permet d'en savoir plus sur le fonctionnement du cache de CouchDB.

  • Je demande la vue by-name : GET http://localhost:5984/_design/contacts/_view/by-name

CouchDB construit la vue (calculs), la met en cache et la renvoie

  • Je redemande la vue by-name : GET http://localhost:5984/_design/contacts/_view/by-name

CouchDB renvoie la vue depuis le cache (pas de calculs).

  • Je demande la liste html depuis les données de la vue by-name : GET http://localhost:5984/example/_design/contacts/_list/html/by-name

CouchDB prend la vue by-name qui est dans le cache (pas de calculs), génère la liste html (calculs), la met en cache et la renvoie.

  • Je redemande la liste html depuis les données de la vue by-name : GET http://localhost:5984/example/_design/contacts/_list/html/by-name

CouchDB renvoie la vue/liste by-name/html depuis le cache (pas de calculs).

  • Je demande la liste html depuis les données de la vue by-name, avec un paramètre personnalisé : GET http://localhost:5984/example/_design/contacts/_list/html/by-name?birthMonth=06

CouchDB prend la vue by-name qui est dans le cache (pas de calculs), génère la liste html (calculs), la met en cache et la renvoie.

  • Je redemande la liste html depuis les données de la vue by-name, avec un paramètre personnalisé : GET http://localhost:5984/example/_design/contacts/_list/html/by-name?birthMonth=06

CouchDB renvoie la vue/liste/arguments by-name/html/birthMonth=06 depuis le cache (pas de calculs).

7. CouchDB sait se dédoubler

Il est possible de répliquer une base de données CouchDB sur une autre. La réplication CouchDB fonctionne de la façon suivante : en répliquant une base db1 sur db2, je réplique tous les changements de la base db1 qui ne sont pas encore dans la base db2. C'est une réplication dite unidirectionnelle : elle réplique les données dans un seul sens. La réplication n'entraîne aucune modification sur la base source.

7.1 Lancement d'une réplication

Lancer une réplication CouchDB est honteusement simple : il suffit de poster sur l'URL _replicate, en passant en paramètres la source et la cible. Au moins une des deux bases spécifiées doit être locale, c'est-à-dire se trouver sur le serveur auquel on se connecte pour initier la réplication.

Afin de répliquer la base de données db1 vers db2, j'envoie l'objet :

{

  'source' : 'db1',

  'target' : 'http://localhost:5984/db2'

}

Ce qui donne :

# creation de la nouvelle base

$ curl -X PUT http://localhost:5984/db2

{"ok":true}

# replication

$ curl -X POST -d "{\"source\":\"db1\",\"target\":\"http://localhost:5984/db2\"}" http://localhost:5984/_replicate

Bien sûr, on peut tout à fait répliquer backupexample sur example :

$ curl -X POST -d "{\"source\":\"http://localhost:5984/db2\",\"target\":\"db1\"}" http://localhost:5984/_replicate

On peut ajouter l'attribut continuous=true dans l'objet envoyé pour demander à CouchDB de synchroniser continuellement la base source sur la base target. Par contre, au reboot du serveur CouchDB, cette synchronisation continue ne se remet pas en place toute seule.

La réplication CouchDB est unidirectionnelle. Pour obtenir une réplication bidirectionnelle, il faut donc créer deux process de réplication unidirectionnelle croisés (db1 => db2 et db2 => db1) en parallèle.

7.2 Les numéros de révision

Pour chaque document enregistré, CouchDB associe un numéro unique de révision. Ce numéro prend la forme chiffre-hash. Chiffre est un compteur du nombre d'événements qui ont été réalisés sur le document. Si on crée un document, puis on le met à jour deux fois, chiffre sera 3. Hash est une somme de contrôle du contenu du document. Par conséquent, si je crée les mêmes documents sur deux bases de données différentes, hash sera identique malgré tout !

$ curl -X PUT -d '{"test": "123", "flag": true}' http://localhost:5984/db1/doc22

{"ok":true,"id":"doc22","rev":"1-6bb69a08b63d8f3e09a8243a974f9376"}

$ curl -X PUT -d '{"test": "123", "flag": true}' http://localhost:5984/db2/doc22

{"ok":true,"id":"doc22","rev":"1-6bb69a08b63d8f3e09a8243a974f9376"}

Il ne faut pas utiliser les numéros de révision pour des systèmes de contrôle de version (type subversion et git) : les anciennes révisions sont effacées lorsqu’on lance une opération compact sur la base de données.

7.3 Gestion des conflits

Comment sont gérés les conflits de version lors d'une réplication ? On crée le document doc1 sur db1, on réplique db1 sur db2. Db1 et db2 contiennent donc le même document, avec le même contenu. Maintenant, on modifie doc1 sur db1 et on le modifie aussi sur db2. On obtient donc deux documents différents sur chacune des bases. Et si on réplique à nouveau ?

Une des règles du moteur CouchDB est de ne jamais utiliser de timestamp dans l'application. En aucun cas CouchDB n'enregistre la date et l'heure d'ajout/modification d'un document. De ce fait, les réplications CouchDB n'utilisent pas de mécanisme de comparaison de date pour connaître la version la plus récente.

En fait, CouchDB ne peut pas savoir « qui a raison » en cas de conflit. Il ne peut pas déduire magiquement quelle version du document conserver. Ceci est lié à la logique de l'application. Dans le cas d'un conflit, CouchDB enregistre les deux versions du document. C'est à l'application de gérer la résolution des conflits, par exemple, via un batch.

Lors de la récupération d'un document, l'option conflicts=true demande à CouchDB d’ajouter, si elles existent, des informations sur les conflits. Ces informations sont stockées dans un attribut _conflicts, sous la forme d'un tableau de toutes les révisions en conflit.

Voila une sortie d'un document contenant un conflit :

$ curl http://localhost:5984/db2/some_doc?conflicts=true

{

    "_id":"some_doc",

    "_rev":"2-549ba1864ecf336ef17cf9834da8c536",

    "test":true,

"_conflicts":

    [

        "2-11cce57f496ac7138b8e9d03fa483ae4"

    ]

}

7.3.1 Un winner et un loser

Lorsqu'on a un conflit sur un document, CouchDB stocke donc les deux documents, avec deux numéros de révisions différentes. Mais alors, que se passe-t-il si on demande au serveur le document, sans préciser la révision que l'on souhaite ? CouchDB compare les numéros de révision et désigne un winner : c'est celui qui sera renvoyé par défaut. L'algorithme de choix du winner n'est pas figé, et les applications sont donc sensées résoudre les conflits. Il n'est pas non plus secret, donc le voilà :

La révision contenant le compteur de modifications (à gauche du tiret) le plus important est élu winner. Si, comme dans notre exemple, ce chiffre est le même, c'est le hash qui est comparé en ASCCI, le plus grand l'emporte. Dans notre exemple, "549ba1864ecf336ef17cf9834da8c536" > "11cce57f496ac7138b8e9d03fa483ae4", c'est donc "549..." qui est élu winner.

7.3.2 Résolution d'un conflit

Résoudre un conflit revient à indiquer à CouchDB quelle version conserver. Si on souhaite conserver la version de la base source de la réplication, c'est très simple: il suffit d'effacer l'autre révision !

$ curl -X DELETE "http://localhost:5984/db2/some_doc?rev=2-11cce57f496ac7138b8e9d03fa483ae4

Si par contre, c'est la version de la base target qui doit être conservée, il faut mettre à jour le document de la base source. Plusieurs solutions sont possibles, la plus simple est sans doute de mettre à jour le document de la base source avec le document de la base target, puis de répliquer la base source sur la base target, et enfin d'effacer la version inutile de la base target.

Traduction en geek :

$ # on met à jour le document de source avec les données du document de target

$ curl -X PUT -d '{"_rev"="2-549ba1864ecf336ef17cf9834da8c536","test":false}' "http://localhost:5984/db1/some_doc"

{"ok":true,"id":"some_doc","rev":"3-..."}

$ # on replique à nouveau de source vers target

$ curl -X POST -d "{\"source\":\"db1\",\"target\":\"http://localhost:5984/db2\"}" http://localhost:5984/_replicate

$ # on efface la révision qui vient de source sur target

$ curl -X DELETE "http://localhost:5984/db2/some_doc?rev=2-549ba1864ecf336ef17cf9834da8c536"

7.4 Liste des documents ayant des conflits

Il peut être utile de pouvoir récupérer la liste des documents d'une base qui ont des conflits. Pour ce faire, il faut créer une vue CouchDB qui émet les conflits si l'attribut spécial _conflicts existe :

function(doc) {

  if(doc._conflicts) {

    emit(doc._conflicts, null);

}

}

Un appel de cette vue donnera un résultat du type :

$ curl http://localhost:5984/db1/_design/general/_view/conflicts?include_docs=true

{

    "total_rows":1,

    "offset":0,

    "rows":

    [

        {

            "id":"doctest",

            "key":

            [

                "4-30c4550922df22d3064f856012d20958"

            ],

            "value":null,

"doc":

            {

                "_id":"doctest",

                "_rev":"7-4da9bda2d4faa3e41a4c017785fdc8c5",

"test":false

            }

        }

    ]

}

8. On n'est pas couché

8.1 Courrier du cœur

Je vois d'avance les lettres arriver en masse au courrier des lecteurs : « Cher Linux Mag, comme toujours, tu as illuminé mes pensées : j'ai d'abord migré tout mon SI sous Linux. Suite à l'article sur CouchDB, j'ai migré toutes mes bases de données Orable et MySQL vers CouchDB, mes dba sont devenus couchdba, et maintenant que tu viens de m'apprendre toutes ces nouveautés, est-ce que je dois bien comprendre ce que je comprends ? »

Eh bien oui. Et c'est même pire.

Une partie des core-développeurs de CouchDB ont l'intime conviction que les applications web, telles que nous les connaissons actuellement, vont évoluer vers des applications hybrides, omniprésentes. Ils redéfinissent les frontières entre les différents composants d'une application, et arrivent à un nouveau modèle. Ce n'est pas Madame Irma qui prend sa boule de cristal pour prédire l'avenir, c'est la vision de certains.

8.2 Il était une fois le Web

Il y a quelques années, une application web classique était composée d'un serveur de base de données, qui contenait les données, un serveur d'application, qui faisait l'ensemble des opérations nécessaires pour récupérer les données et les envoyer au navigateur. Ce dernier (le navigateur) ne faisait pas grand chose d'autre qu'afficher les pages web.

Puis on a commencé à se dire qu’il serait bien de mettre un peu d'intelligence dans le navigateur, histoire de pouvoir mettre de jolies animations, des contrôles plus interactifs, des requêtes au serveur web en tâche de fond, ... Javascript a connu un regain d'intérêt. Des bibliothèques remarquables ont vu le jour (JQuery et consorts). On ne recharge plus la page : c'est Javascript qui mène la barque, il répond aux événements de l'interface utilisateur, dialogue en direct avec le serveur par AJAX et met à jour l'interface utilisateur en conséquence.

Ensuite, certains se sont dits que les bases de données classiques (SGBD) n'étaient pas forcément adaptées à du contenu de type web. De plus, l'aspect structuré, indispensable dans certains contextes, semblait freiner la créativité et l'évolution des applications. On a donc créé des bases de données dites NoSQL, dont CouchDB fait partie. 2009 se situe là dans la présente théorie de l'évolution.

Petit à petit, les utilisateurs CouchDB prennent conscience que CouchDB parle nativement avec un navigateur (protocole HTTP), permet d'importer et d'exporter des données avec ce navigateur (JSON), que CouchDB peut aussi envoyer du HTML ou tout autre dialecte (shows et lists), et qu'il peut même contenir des médias (les attachements aux documents) : ils imaginent donc un monde ou il n'y a plus de serveur d'application : son travail est réparti sur la base de documents d'une part, et sur l'intelligence du navigateur d'autre part. Les synergies sont nombreuses et les deux composants se contrôlent avec le même langage : le Javascript.

Le coup de massue final : CouchDB supporte la réplication des bases entre serveurs ! Je peux avoir mon application en local sur mon ordinateur et m'en servir même déconnecté. Lorsque je me reconnecte, les bases locales et distantes se synchronisent. Pour déployer une nouvelle version de l'application, rien de plus simple : il suffit de mettre à jour les design documents sur le serveur internet, l'application se mettra automatiquement à jour à la prochaine réplication. Énorme ! Et comment s'appelle ce genre d'application ? Facile : une CouchApp !

Conclusion

Une idée futuriste, pensez-vous ? Ces gens veulent mettre à néant des années de Python, PHP, .Net (oohhh !!) ? Enlever nos serveurs d'applications favoris ? Passer de Linux Apache MySQL PHP à Linux CouchDB ? Rassurez-vous, il ne s'agit pas de changer tous les sites web, leur proposition n'est pas une solution miracle à tous les problèmes. Par contre, dans le contexte d'une application web, c'est l'idée. Et l'invasion a déjà commencé. Ubuntu, la distribution Linux qu'on aime conseiller, implémente, dans la version 9.10, un serveur CouchDB par utilisateur, répliqué (si on le souhaite) sur Internet. Celui-ci gère, par exemple, le carnet d'adresses. Certains militent pour une implémentation du HTML5 Web Storage, directement dans le navigateur, via une API CouchDB plutôt que SQL. On imagine facilement la puissance d'un équivalent Google Docs, Wordpress, Deezer, avec cette architecture. L'application est partout, à la fois en local et sur Internet, sur le smartphone et dans le cloud, toujours accessible !

Liens

Apache CouchDB : http://couchdb.apache.org

CouchDB dans Ubuntu donne naissance à Ubuntu One : https://one.ubuntu.com/

Emulation CouchDB dans Firefox : http://hg.toolness.com/browser-couch/raw-file/blog-post/index.html

Le framework couchapp : http://github.com/jchris/couchapp

Le mouvement NoSQL : http://en.wikipedia.org/wiki/NoSQL