CouchDB: Una pequeña introducción (Parte III)

Tagged:

Filtrado de vistas y View Collations

 

CouchDB permite únicamente filtrar por la clave de las parejas clave-valor generadas por una vista. Para ello en la URL simplemente hay que añadirle los campos keystart y/o keyend. Así, por ejemplo si quisieramos filtrar todos los telefonos que empiezan por 123, usariamos la siguiente funcion map:

function (doc){

       for (ph in doc.Teléfono)
          emit(doc.Teléfono[ph], doc.Nombre);
     }

Y llamaríamos a nuestra vista pasandole startkey="123-" y endkey="124-":

 

http://url_del_servidor:5984/base_de_datos/_design/nombre_documento/_view/nombre_vista&startkey="123-"&endkey="124-"

View Collations

View Collations es una técnica utilizada para obtener resultados de diferentes tipos de documentos y poder filtrarlos. Para ello usaremos la función map para generar parejas clave-valor, pero nos aprovecharemos de las capacidades de filtrado por clave que nos suministra CouchDB para obtener los resultados deseados.

 

Por ejemplo, supongamos que a nuestra base de datos de tarjetas de presentación le añadimos documentos que indican quien ha introducido esa tarjeta de presentación. Para realizar esta modificación añadiremos a los documentos de tarjeta de visita dos propiedades nuevas, el tipo y el autor. El tipo nos permitirá diferenciar entre los dos tipos de documentos, y el autor contendrá el identificador de un documento con información del autor.

 

{

        "Tipo": "Tarjeta de visita",

        "Nombre": "Jane Doe",

        "Telefono": [ "456-789-465", "999-876-543" ],

        "Dirección": "Cl. Void, 21",

        "Skype": "JaneDoe",

        "Autor": "FrankDoe"

     }

 

Y además añadiremos los documentos de tipo 'Autor' que seguiran el siguiente esquema:

 

{

       "Tipo": "Autor",

       "Nombre": "Frank Doe",

     }

 

Para obtener un listado de teléfonos y autores, a modo de foreign key de una base de datos clásica, tendríamos que crear esta función map:

 

function(doc) {
  if (doc.Tipo == "Autor")
    emit(doc.Nombre,doc);
  else
    emit(doc.Autor,doc);
}

 

Esta función nos suministrará una lista de clave-valor, en la cual tendremos parejas del tipo Nombre -  Documento para los documentos de tipo "Autor" y Autor - Documento para los documentos de tipo "Tarjeta de visita".

 

Ahora añadiremos una función reduce para completar nuestro listado:

 

function(keys, values, rereduce)
{
  var autorestelefono = [];
  for(var i = 0; i < values.length; i++)
  {
    if(values[i].Tipo == "Tarjeta de visita")
    {
      autorestelefono.push([values[i].Nombre,values[i].Teléfono]);
    }
  }
  return autorestelefono;
}

 

Con esta función buscaremos todos los elementos  de tipo "Tarjeta de visita" y para ellos devolveremos un array con el Nombre de la tarjeta de visita y los telefonos. Como la clave de estos elementos coincide con la clave de los elementos de tipo Autor generados en la función map, es decir coincide con el nombre de la Foreign Key, tendremos una lista con clave : Nombre del autor y valor: Nombre de la tarjeta de visita y teléfono.

 

Esta técnica nos permite hacer busquedas y filtrados avanzados, pero no permite hacer filtrados del estilo de una base de datos clásica. Para este tipo de filtrados la mejor solución es usar Couchdb-Lucene ( http://github.com/rnewson/couchdb-lucene/tree/master ).

 

A continuación...

 

Hasta aquí hemos visto la mayoría de los conceptos básicos de CouchDB, faltaría ver los _lists y los _shows para formatear las salidas de las vistas, pero esto lo dejaremos para más adelante. En el siguiente post hablaremos sobre CouchDB-Lucene y como utilizarlo para realizar busquedas de texto completas. Si tienen alguna duda, pregunta o sugerencia, dejen un comentario.

 

 

Problemas con K3b (Resuelto!)

Llevo semanas con problemas con mi K3b. No detectaba mi grabadora, a pesar de que cdrecord me decía que mi unidad estába ahí una y otra vez.

Mirando por cientos de webs no daba con la solución al problema, hasta que he llegado a esta web: http://linux.derkeiler.com/Mailing-Lists/SuSE/2009-04/msg00922.html

Una de las cosas que se planteaba era si tenía problemas con Hal y ya era lo último que me faltaba por mirar, asi que ... sorpresa! Mi demonio de hal estaba parado. Supongo que gran parte de culpa la tiene en arrancar las X a mano sin Kdm y sin haber configurado correctamente el entorno de KDE.

Supongo que me volvera a pasar  y me volveré a olvidar de la solución así que me uso a mi mismo de chuleta para la próxima.

CouchDB: Una pequeña introducción (Parte II)

Tagged:

Vistas, ¿Qué son y como se usan?

Una vista no es más que un documento de CouchDB que contiene un vector asociativo llamado views, donde se almacenan las vistas. Cada vista se representa a su vez por un vector que contiene dos funciones, map y reduce. Además, este documento debe tener un identificador de la forma  "_design/" seguido del nombre de nuestro documento de diseño.

Para acceder a una vista tendrémos que apuntar nuestro navegador a la siguiente dirección:

http://url_del_servidor:5984/base_de_datos/_design/id_documento/_view/nombre_vista

La función map:

La función map se llama una vez para cada documento almacenado en la base de datos, utilizando dicho documento como parametro de entrada. Esto implica que la función map solo nos permitirá conocer los valores del documento que estámos tratando. Aunque pueda parecer una limitación esta forma de trabajar permite que CouchDB pueda generar resultados de forma incremental y que pueda paralelizar este proceso de forma óptima.

El objetivo de la función map es generar filas de la forma clave-valor. Para cada documento se pueden generar tantas filas como se deseen. Veamos un ejemplo. Supongamos que queremos obtener el nombre y el teléfono de todas las tarjetas de presentación que tenemos almacenadas. Para ello construiremos un documento cuyo id sera "_design/telefonos" y que únicamente contendrá la función map siguiente:

 

function (doc) {

  for (telefono in doc.telefono) {

      emit(doc.nombre, doc.telefono[telefono]);

  }

}

De está forma obtendremos un listado de parejas clave-valor , cuya clave será el nombre de la persona y el valor será el teléfono. Para las personas que tengan más de un teléfono tendremos tantas filas como teléfonos tengamos almacenados.

 

La función reduce:

Está función se encarga de procesar la salida de la función map, y en caso necesario la propia salida de reduce. Se utiliza para agrupar valores, realizar calculos con las salidas de map, y cualquier otro proceso dependiente de otro valor. Recibe como parametros un array de claves, un array con los valores, y un array con la salida anterior de la función reduce.

 

Volviendo al ejemplo de las tarjetas, podríamos querer agrupar todos los telefonos de una misma persona en una única fila. Para ello crearíamos una función reduce como la siguiente:

 

function(keys, values, combine) {

        return value;

     }

 

De está manera para cada clave devuelta por la función map devolverá todos los valores asociados, obteniendo el efecto que queríamos.

 

Uniendo la función map y reduce tendremos un documento final como este:

 

{
"_id": "_design/telefonos",
"_rev": "1-1520601632",
"language": "javascript",
"views": {
"pornombre": {
"map": "function(doc) {
for(ph in doc.Teléfono) {
emit(doc.Nombre, doc.Teléfono[ph]);
}
}"
,
"reduce": "function(keys, value, combine){
return value;
}"

}
}
}

A continuación...

En la siguiente entrega explicaré como funciona la recopilación de vistas (View Collation) y como filtrar los resultados obtenidos de una vista  mediante parametros en la URL. Si tienen alguna duda, pregunta o sugerencia, dejen un comentario.

 

CouchDB: Una pequeña introducción (Parte I)

Tagged:

¿Qué es CouchDB?

 

CouchDB es un motor de base de datos basado en documentos.

Esto quiere decir que, al contrario que las bases de datos tradicionales, CouchDB no utiliza tablas. La filosofía de CouchDB se basa en imitar la realidad, almacenando todo el conocimiento relacionado en un único documento. En la vida real, cuando tomamos los datos de una persona, tendemos a escribir todos los datos relacionados lo más cerca posible. Por ejemplo, en una tarjeta de presentación tenemos  nombre, teléfono, dirección y correo electrónico en un único trozo de papel, en vez de guardar un directorio de nombres, otro de teléfonos y otro de direcciones relacionados entre sí.

Otra característica que CouchDB copia de la realidad es la flexibilidad de los documentos. En el mundo real, cuando tomamos anotaciones, no lo hacemos siempre de la misma manera. Volviendo al ejemplo de la tarjeta de presentación, no siempre dejamos un hueco para un segundo teléfono, ni reservamos espacio para un segundo nombre. Simplemente, escribimos los datos que consideramos relevantes para cada tarjeta. CouchDB sigue este modelo, dejando que cada documento tenga su propia estructura.

Entrando en la parte más técnica, los documentos en CouchDB se almacenan en JSON. Con ello conseguimos una rápida transformación de los documentos a objetos en los lenguajes de programación, a la vez que se pueden entender fácilmente por cualquier persona.

Por ejemplo, para representar la tarjeta de presentación de John Doe podríamos tener el siguiente documento:

 

{

        "Nombre": "John Doe",

        "Teléfono": ["123-123-321"],

        "Dirección": "Cl. Void, 12",

        "E-mail": "john@doe.org"

      }

 

Y en la misma base de datos podríamos tener la tarjeta de presentación de Jane Doe en la misma base de datos sin necesidad de hacer nada para indicar que no sigue el mismo esquema:

 

{

        "Nombre": "Jane Doe",

        "Telefono": [ "456-789-465", "999-876-543" ],

        "Dirección": "Cl. Void, 21",

        "Skype": "JaneDoe"

     }

 

Independientemente de la estructura que elijamos, CouchDB establece dos campos para cada documento. El campo "_id" que almacena un identificador único para cada documento y el campo "_rev" que nos permite identificar entre todas las revisiones del mismo documento.

 

CouchDB es una base de datos distribuida y tolerante a fallos.

Es decir, podemos tener nuestra base de datos replicada por toda la red, teniendo copias de la misma en diferentes sitios. Cada copia de nuestra base de datos puede ser modificada indistintamente y se pueden sincronizar  automágicamente. En caso de producirse un conflicto irresoluble, existen mecanimos para evitar la perdida de datos.

Imaginemos que tenemos la información de John en nuestra base de datos en el trabajo y que además la tenemos replicada en una base de datos que tenemos almacenada en casa. John nos llama a casa y nos informa que se va a vivir con Jane, así que actualizamos su dirección en nuestra base de datos. Al día siguiente llegamos al trabajo y recordamos que John se ha mudado a casa de Jane, así que sincronizamos los datos con nuestra base de datos de casa y automágicamente nuestra base de datos del trabajo contiene la nueva dirección de John.

Casualmente, ese día mientras trabajamos en la contabilidad, cometemos un error y modificamos la tarjeta de visita de John borrando todos los datos almacenados en ella sobreescribiendolos con datos de la contabilidad. Al mismo tiempo que cometíamos este error, alguien en casa, actualiza el número de teléfono de John. Cuando tratemos de sincronizar las bases de datos tendremos un conflicto, ya que la base de datos no sabrá cual de las dos versiones es la correcta.

 

Para resolver  esta situación CouchDB establece un mecanismo de protección, guardando las dos versiones y declarándolas como "En conflicto" hasta que el usuario decida cual de las dos es la versión correcta. Hasta ese momento, ante cualquier consulta, el documento que se mostrará el documento cuya ruta de acceso sea más larga.

Hay que tener en cuenta que cuando se produce un conflicto y se establecen dos versiones del documento, aunque estás estén marcadas como "En conflicto", siguen siendo documentos normales. Por lo tanto en caso de replicar una base de datos a una tercera máquina, también replicaríamos el conflicto.

Otro detalle importante a tener en cuenta en la replicación de bases de datos con CouchDB es que antes de hacer una replicación, CouchDB compacta las bases de datos, eliminando cualquier revisión anterior de los documentos que no se encuentren en conflicto. Esto es importante a la hora de plantear sistemas de control de versiones, ya que aunque CouchDB mantenga una revisión de los documentos, en cualquier momento la podemos perder por una replicación o una compactación de la base de datos.

 

CouchDB es una base de datos con un API RESTful.

Para poder acceder a los datos en CouchDB, tanto para consultarlos, modificarlos o eliminarlos. CouchDB suministra un API REST por HTTP. Esta API nos permite usar los comandos HTTP COPY, DELETE, GET, MOVE, POST y PUT para modificar documentos, bases de datos y vistas. Por ejemplo, para crear la tarjeta de identificación de John, nos bastaría con enviar el comando PUT indicando el identificador del documento (_id) en la URL y la estructura JSON del documento, como la que vimos anteriormente,  en la sección de datos.

 

A continuación...

En la siguiente entrega explicaré como funciona el sistema de vistas de CouchDB y como hacer consultas avanzadas. Si tienen alguna duda, pregunta o sugerencia, dejen un comentario.

 

iRvz = iMac + iPhone

Al final he caído y me he comprado un iPod Touch y un iMac de 20".

Hacía tiempo que llevaba picándome la curiosidad por los productos de Apple y la verdad es que el iPod me ha sorprendido gratamente. Y es que he tenido varios cacharros en la misma linea, desde una iPaq hasta la psp, pero ninguno de ellos me dejo tan contento. No se si es el tema de la interfaz táctil, el tema de que es muy rápido para acceder a él (poniéndolo en reposo) o que tiene una interfáz para el teclado realmente cómoda pero el caso es que ahora es un gadget que va siempre en mi bolsillo.

Por la contra el iMac no me ha dejado con tan buen sabor de boca, como hardware es increible, pero por el mismo precio se puede conseguir un hardware mil veces más dopado. Haciendo números por encima con que me compre el iMac me da para un pc con Quad core, el doble de memoria , el cuadruple de disco duro, una pantalla de 24" y aún me sobra dinero. Y a sabiendas de esto decidí comprarme el iMac, la razón principal es que no quería perder tiempo hackeando el pc hasta el infinito para meterle MacOS, prefería usar ese tiempo en programar para MacOS o para el iPod.

En el tema de software, yo no veo las maravillas que predican los maqueros en MacOS. Por el lado de la interfaz me encuentro muy limitado, me siento bastante incomodo con un escritorio en el que no puedo o no se como poner las ventanas pegajosas a todos los escritorios o las ventanas "On Top". Por otro lado, el inexistente sistema de paquetes me hace sentir que pierdo totalmente el control de lo que tengo instalado y lo que no. Y si encima te metes a programar, peor todavía, algunas cosas tiradas en la estructura linux/unix (/usr/lib, /usr/include), otras tiradas en la estructura MacOS (/Developer/framework).

Aún así hay un punto que no les puedo negar, el compilador de c++ es bastante más estricto en los chequeos de tipos y eso me ayuda bastante a cazar bugs. Y por otro lado que cuando una aplicación caiga, te salga una ventanita con la traza de tu programa también es de bastante agradecer.

Por lo pronto, anuncio por aquí y así me obligo un poco a cumplirlo, que en breve intentaré meter algún tutorial de programación del iPod, a la vez que voy haciendo la aplicación chorra que tengo en mente.

 

Primera reunión canaria de codepixel

Ayer tuve el placer de conocer en persona a Javier Loureiro, creador de codepixel e integrante de Ilion Studios, y a Thai Dam.
 
Resultó una tarde muy interesante, hablando de cosillas de gráficos, de codepixel, y de como arreglar el mundo en general delante de una cerveza. Una vez más hablar con cierto tipo de gente vuelve a sacarme las ganas de hacer cosas. Escribir más en el blog, acabar pruebas que he dejado a medias, etc etc.... A ver cuanto me dura está vez el subidón.

Nuevo trabajo, nuevo blog

He empezado en un nuevo trabajo, y he decidido re abrir mi blog.

 

El trabajo

Logo Banot.net

En sueños...

Anoche medio soñando, medio despierto (tenía un dolor de cabeza bestial), se paseo está frase por mi cabeza. Creo que puede ser un bueno comienzo para una historia y antes de que se me olvide:

"Realmente  existen dos razas, los gorilas y los angeles. Los humanos somos lo que está en medio."

No se si algún día la convertiré en una historia completa pero ... ahí queda Laughing

 

Que bien sienta el deporte

Tagged:

Hoy he vuelto a engancharme al volley. Hacía siglos que no jugábamos y tenía un mono impresionante.

El caso es que para llevar tanto tiempo sin jugar no me encontré en tan baja forma como me esperaba.

Mañana tendré agujetas por un tubo... pero después de la duchita que me acabo de pegar, que bien me siento. Mañana me moriré en el curro y despues toca clase de bateria, juaz a ver que tal...

Tras 3 horitas de juego, casí morirme varias veces he salido con las endorfinas por las nubes.

Los culpables de esto han sido:

Trucos para OpenGL

Llevo toda la semana queriendo escribir algo no técnico... pero me lo guardo para mañana o pasado.

Para hoy va un artículo bastante friki sobre OpenGL. Y es que a raíz de la discusión sobre OpenGL 3.0 en todos lados y en concreto sobre el hilo de codepixel, he estado aprendiendo mucho sobre cosas que todo buen desarrollador debía de saber y que yo no teía ni idea. En el hilo de discusión de codepixel recomendaron este video: "OpenGL in 2006 blender conference" en el que se explican muchas técnicas para mejorar el rendimiendo de los programas hechos en OpenGL. Aquí va una listilla de cosas a tener en cuenta a modo de resumén:

 

  1. No usar el modo inmediato (glBegin();glEnd(); ) y en vez de esto usar VA (Vertex Array). Yo en esta llevo cayendo toda mi vida,creo que no he usado VA nunca. Pero partiendo que el modo inmediato en OpenGL 3.0 pasa a estar "deprecado" y en la 3.1 posiblemente desaparezca y que según cuentan en el video de la conferencia de blender es más lento que el caballo del malo... es para pensarselo.
  2. Usar VBO (Vertex Buffer Object) para datos estáticos. Al estar en la memoria de la tarjeta de vídeo se gana muchisimo rendimiento.
  3. User FBO (Frame Buffer Objects). Esta extensión nos permite alterar las imagenes directamente a modo de frame buffer. Esto nos permite desde renderizar cosas a una textura hasta hacer los efectos tan chulos que en los 80 se hacían escribiendo directamente en el frame buffer ( Frame Buffer Object 101 en Gamedev)
  4. No cambiar los estados de la máquina de estados de OpenGL. Esto puede ser contraproducente ya que debería de ser el driver el único que cambiase los estados, al cambiarlo programaticamente provocamos más cambios innecesarios.

Bueno, es una lista de consejillos que, al menos yo voy a tener en cuenta a partir de ahora.

 

Distribuir contenido