<%shared># my $h2 = 1; #Inicialización del contador my $ej = 1; #Contador de ejercicios <& header.mhtml, titulo_tema => 'FluidDB', keywords => 'XML, Javascript, AJAX, FluidDB, web of things', description => "Introducción al uso de FluidDB desde Perl" &> <&| filter.mhtml &>
<& h2.mhtml, h2 => \$h2, titulo => 'FluidDB: Qué es', abbrev => 'plus' &>

FluidDB se define a sí misma como la base de datos con el corazón de un wiki. En vez de usar el concepto tradicional de base de datos que reflejan una estructura de filas y columnas, FluidDB usa conceptos totalmente diferentes: objetos y etiquetas (tags). Los objetos tienen etiquetas, y a su vez a las etiquetas se les pueden asignar valores, pero en principio objetos y etiquetas son entidades independientes con los valores asignados estableciendo una relación entre ambos.

Además, los objetos no pertenecen a nadie; cualquiera puede añadir relaciones, es decir, asignarles etiquetas; sin embargo, las etiquetas tienen una serie de restricciones de uso que hacen que, en principio, sólo las pueda usar quien las crea (o destruirlas, o asignarles valores), aunque se pueden cambiar esas políticas iniciales por otras menos restrictivas de forma que cualquiera pueda usar una etiqueta si el usuario lo deja

Lo que se pretende con FluidDB, creada por una empresa barcelonesa con capital extranjero, es que sirva de base a la internet de las cosas, una serie de relaciones basadas en objetos (que pueden representar o no cosas del mundo real), y relaciones establecidas entre ellos a través de etiquetas. FluidDB es una forma eficiente de acceder a esos objetos a través de las relaciones, usando un lenguaje de peticiones (query) muy simple

. <& h2.mhtml, h2 => \$h2, titulo => 'Usando FluidDB', abbrev => 'using' &>

FluidDB funciona ahora mismo en dos instancias: un sandbox que permite trabajar con un nombre de usuario y clave genéricos (test/test) y con un acceso identificado reservando un nombre de usuario y solicitando el acceso a través de alguno de los múltiples métodos que ofrece. El sandbox permite acceder a toda la funcionalidad, de todas formas, salvo que estarás compartiendo usuario con todos los demás.

El API es de tipo :wiki:REST:, usando HTTP para las peticiones y respuestas, y generalmente :wiki:JSON: para codificación de la información. Sin embargo, lo más habitual (en este y otros casos) es que el transporte de bajo nivel se esconda bajo una librería o módulo en algún lenguaje de programación. Hay una docena de librerías que se pueden usar para trabajar con ella, pero nosotros usaremos el módulo Perl Net::FluidDB, de Xavier Noria, todavía en evolución pero suficientemente usable como para poder trabajar con él

<& h2.mhtml, h2 => \$h2, titulo => 'Creando objetos', abbrev => 'obj' &>

Los objetos son el corazón de FluidDB. El interfaz es bastante directo, como se puede ver en el siguiente programa (todos los ejemplos mencionados aquí, y alguno más, te lo puedes descargar en este fichero). #!/usr/bin/perl use strict; use warnings; use Net::FluidDB; #Open test connection my $fdb = Net::FluidDB->new_for_testing; # create object, with optional about my $object = Net::FluidDB::Object->new( fdb => $fdb, about => "Pruebas para tutorial SFD" ); $object->create; my $this_id = $object->id; print "El objeto ha recibido el ID $this_id\n"; # returns the object's ID in FluidDB

En este programa se importa, como es habitual, el módulo. Luego se conecta uno a la base de datos obteniendo un handle $fdb que se usa para crear el objeto más adelante. La única característica del objeto es el $about$, un descriptor único al que podemos asignar valores siguiendo alguna convención (por ejemplo misitio.com/objetos/chulis). El objeto no se crea efectivamente hasta que se llama a $create$, que es cuando se hace la petición a FluidDB y se devuelve un ID único.

<& h2.mhtml, h2 => \$h2, titulo => 'Creando etiquetas', abbrev => 'tags' &>

Creado un objeto, podemos intentar asignarle etiquetas; la forma de hacerlo es bastante similar:

#!/usr/bin/perl use strict; use warnings; use Net::FluidDB; use Net::FluidDB::Tag; use YAML qw(LoadFile); my $conf = LoadFile('conf.yaml') || die "No puedo cargar : $@\n"; my ( $tag_name, $description ) = @ARGV; #Open test connection my $fdb = Net::FluidDB->new( username => $conf->{'username'}, password => $conf->{'password'}); #Creamos un tag todo my $path = $conf->{'username'} . "/$tag_name"; my $tag = Net::FluidDB::Tag->new( fdb => $fdb, description => $description, indexed => 1, path => $path ); $tag->create;

En este caso hacemos más o menos lo mismo que antes, salvo que en vez de usar new_for_testing (usuario/clave test/test) uso mi propio nombre, que ya me lo han dado, chincha rabiña. Si usas el de test tampoco cambia mucho.

Evidentemente hay que comenzar con la conexión a la BD, y luego se crea el tag, que también tendrá una descripción. El tag es siempre de la forma nombre_usuario/etiqueta (con más /, posiblemente, luego lo veremos); el tag lleva siempre asociado quien lo ha creado, y es independiente del valor que se le asigne sobre un objeto determinado. Se crea igual que antes: se crea el objeto y luego se "crea" de veras llamando a $create$.

<& h2.mhtml, h2 => \$h2, titulo => 'Asignando etiquetas', abbrev => 'tagging' &>

Vamos a ver la forma de relacionar etiquetas y objetos; como hemos visto los objetos no pertenecen a nadie y las etiquetas, sin no se dice nada, pertenecen al usuario. Por lo tanto una relación objeto-etiqueta es siempre una relación entre un objeto y el usuario que creó la etiqueta, pero puede ser más. A una etiqueta sobre un objeto le puedes asignar cualquier valor: un número, una cadena, un array, un documento completo, una imagen... puede ser cualquier cosa. Vamos a empezar por lo más simple: un sistema que recuerde tareas por hacer, y en la que los objetos sean fechas y se usen etiquetas para indicar qué es lo que hay que hacer y qué prioridad tiene. Lo hacemos en el siguiente programa:

#!/usr/bin/perl use strict; use warnings; use Net::FluidDB; use Net::FluidDB::Tag; use YAML qw(LoadFile); my $conf = LoadFile('conf.yaml') || die "No puedo cargar : $@\n"; my ( $date, $todo, $prioridad ) = @ARGV; #Open test connection my $fdb = Net::FluidDB->new( username => $conf->{'username'}, password => $conf->{'password'}); # Crea el objeto, o lo recupera my $object = Net::FluidDB::Object->new( fdb => $fdb, about => "OSL.ugr.es/tutorial/Tareas/$date" ); $object->create; my $this_id = $object->id; print "El objeto ha recibido el ID $this_id\n"; # returns the object's ID in FluidDB #Vamos a añadirles tags my $prio_tag = Net::FluidDB::Tag->get($fdb, "jjmerelo/prioridad", description => 1); $object->tag($prio_tag, int($prioridad)); my $todo_tag = Net::FluidDB::Tag->get($fdb, "jjmerelo/todo", description => 1); $object->tag($todo_tag, $todo );

Tomando valores de la línea de comandos (que son siempre cadenas, aunque tengan un valor numérico), creamos (o recuperamos, FluidDB si encuentra un objeto con el $about$ puesto nos devuelve el objeto ya construído) y posteriormente recuperamos las etiquetas que nos interesan; recordad que sólo se pueden asignar etiquetas que han sido creadas anteriormente (y que tengamos permiso de asignar, claro). Con $tag$ se asigna el valor a la etiqueta, que en el primer caso se convierte en numérico con el typecasting $int$ y en el segundo caso ($jjmerelo/todo$) es una simple cadena.

En este caso hemos construído explícitamente un objeto para cada tag, pero en realidad no es necesario: se puede simplemente hacer $object->tag("username/tag", $valor). Y recordamos que $valor puede ser cualquier estructura de datos, por ejemplo, $valor = ['1', 'x', '2'].

<& h2.mhtml, h2 => \$h2, titulo => 'Buscando', abbrev => 'plus' &>

De poco sirver crear tantas cosas si luego no puedes recuperarlas de forma rápida y eficiente. El lenguaje de peticiones (queries) es simple, pero permite hacer todo tipo de peticiones complejas combinando peticiones más simples con AND y OR. Por ejemplo, podemos querer recuperar todos los objetos cuya prioridad esté por debajo de un límite con el programa siguiente:

use strict; use warnings; use lib '../net-fluiddb/lib'; use Net::FluidDB; use Net::FluidDB::Tag; use Net::FluidDB::Object; use YAML qw(LoadFile); my $limit = shift || 0; my $conf = LoadFile('conf.yaml') || die "No puedo cargar : $@\n"; #Open test connection my $fdb = Net::FluidDB->new( username => $conf->{'username'}, password => $conf->{'password'}); # Crea el objeto, o lo recupera my $path = $fdb->username."/prioridad"; my @object_ids = Net::FluidDB::Object->search( $fdb, "$path <= $limit" ); for my $o (@object_ids ) { my $object = Net::FluidDB::Object->get( $fdb, $o, about => 1 ); my @tag_paths = @{$object->tag_paths}; print "\n* Objeto ", $object->about; for my $t (@tag_paths ) { print "\n\t* $t => ", $object->value( $t ), "."; } }

Aquí usamos la función $search$, a la que se le pasa el handle y el query; en este caso que la etiqueta "jjmerelo/prioridad" (o del usuario que le hayamos dado) sea menor o igual que el límite. Como se ve, el comando no devuelve objetos, sino IDs de objetos; los objetos podemos construirlos posteriormente, y recuperar el $tag_path$, conjunto de etiquetas que tiene cada objeto asignado. Este programa devolverá algo así

[jmerelo@localhost code]$ ./limit.pl 1 * Objeto OSL.ugr.es/tutorial/Tareas/2011-02-03 * jjmerelo/todo => Dormir. * fluiddb/about => OSL.ugr.es/tutorial/Tareas/2011-02-03. * jjmerelo/prioridad => 1. * Objeto OSL.ugr.es/tutorial/Tareas/2011-01-01 * jjmerelo/todo => Despertar. * fluiddb/about => OSL.ugr.es/tutorial/Tareas/2011-01-01. * jjmerelo/prioridad => 1. * Objeto OSL.ugr.es/tutorial/Tareas/2011-02-04 * jjmerelo/todo => Ir. * fluiddb/about => OSL.ugr.es/tutorial/Tareas/2011-02-04. * jjmerelo/prioridad => 1. * Objeto OSL.ugr.es/tutorial/Tareas/2012-12-12 * jjmerelo/todo => Nada. * fluiddb/about => OSL.ugr.es/tutorial/Tareas/2012-12-12. * jjmerelo/prioridad => 1.

El query devuelve cuatro objetos, y de esos objetos imprimimos todas las etiquetas; como se ve, $about$ es una etiqueta más, por lo que también se podrían hacer queries sobre ella

<& h2.mhtml, h2 => \$h2, titulo => 'Y más cosas', abbrev => 'plus' &>

Este mini-tutorial sólo pretende ser una introducción a FluidDB que está todavía en alfa e incluyendo mejoras casi de forma continua. Quedan por explorar los espacios de nombres (si quieres crear etiquetas estructuradas más complejas), los permisos (para decir quién puede usar tus etiquetas y qué puede hacer con ellas), y queries más completas. Pero con esto se pretende dar una idea más o menos general, para que os abra el apetito y os lancéis a usarlo y a desarrollar cosas para él. En el futuro será más fácil: se espera un interfaz XMPP y Thrift, que no sé lo que es, pero debe ser chulo.

<& h2.mhtml, h2 => \$h2, titulo => 'Material adicional', abbrev => 'plus' &>

En este momento, FluidDB está todavía en alfa, así que no hay demasiado material sobre ella. El principal sitio de referencia es la web de la compañía, que incluye blogs con información diversa; también hay documentación sobre el API y diferentes explicaciones de alto nivel de blogs externos.

El módulo Perl es reciente, pero hay muchísimos más.

<& footer.mhtml &>