Cómo : Implementar el control de versiones de documentos con Couchbase

[This blog was syndicated from http://blog.grallandco.com]

Introducción

Los desarrolladores me preguntan a menudo cómo "versionar" documentos con Couchbase 2.0. La respuesta corta es: los clientes y el servidor no exponen tal característica, pero es bastante fácil de implementar.
En este artículo utilizaré un enfoque básico, que usted podrá ampliar en función de las necesidades de su empresa.

Diseño

Lo primero es seleccionar cómo "almacenar/organizar" las versiones de tu documento, y para ello tienes diferentes diseños:
  • copiar las versiones del documento en nuevos documentos
  • copiar las versiones del documento en una lista de documentos incrustados
  • almacenar la lista de atributos que se han cambiado en un elemento incrustado (o nuevos documentos)
  • guardar el "delta"
  • ...
Tendrá que elegir el diseño en función de los requisitos de su aplicación (lógica de negocio, tamaño del conjunto de datos, ...). Para este artículo, vamos a utilizar uno de los enfoques más simplistas: crear un nuevo documento para cada versión con las siguientes reglas para las claves:
  1. La versión actual es una simple Clave/Documento, sin cambios en la clave.
  2. La versión es una copia del documento, y el número de versión se añade a la clave.
Esto parece:
Versión actual   mykey
Versión 1   miclave::v1
Versión 2   mykey::v2
     …

Con este enfoque, las aplicaciones existentes siempre utilizarán la versión actual del documento, ya que la clave no se modifica. Pero este enfoque crea nuevos documentos que serán indexados por las vistas existentes.

Por ejemplo, en la aplicación Beer Sample, se utiliza la siguiente vista para listar la cerveza por su nombre:

function (doc, meta) {
if(doc.type && doc.type == "beer") {
emit(doc.nombre);
}
}

Es bastante sencillo "soportar" el versionado sin afectar al código existente, excepto a la propia vista. La nueva vista necesita emitir keys,value sólo para la versión actual del documento. Este es el código de la nueva vista:

function (doc, meta) {
if(doc.type && doc.type == "beer" && (meta.id).indexOf("::v") == -1 ) {
emit(doc.nombre);
}
}
Con este cambio, las aplicaciones existentes que utilizan esta vista seguirán funcionando con el mismo comportamiento.

Aplicación del control de versiones

Basado en este diseño, cuando la aplicación necesita versionar el documento, debería ocurrir la siguiente lógica:
  1. Obtener la versión actual del documento
  2. Incrementar el número de versión (por ejemplo, utilizando otra clave que mantenga el número de versión de cada documento).
  3. Crear la versión con la nueva clave "mykey::v1"
  4. Guardar la versión actual del documento
Veamos el código en Java
  Objeto obj = cliente.get(clave);
if (obj != null) {
// obtener la siguiente versión, crear o utilizar la clave: mykey_version
long version = client.incr(key + "_version", 1, 1);
String keyForVersion = key + "::v" + version; // mykey::v1
intentar {
client.set(keyForVersion, obj).get();
} catch (Exception e) {
logger.severe("No se puede guardar la versión "+ versión + " de la clave "+ clave +" - Error: "+ e.getMessage() );
}
}
cliente.set(clave, valor);

Muy sencillo, ¿verdad?

La aplicación puede acceder al documento utilizando la clave, pero también obtener una versión o la lista de todas las versiones, esta es una de las razones por las que es interesante crear una clave (mi_version_clave), y utilízalo también para eliminar documentos y versiones relacionadas.

Basándonos en el comentario anterior, la operación de borrado tiene el siguiente aspecto:

  Objeto obj = cliente.get(clave);
// primero hay que borrar todas las versiones
Objeto vObject = this.get(key + "_version");
if (vObject != null) {
long biggerVersion = Long.parseLong((String) vObject);
intentar {
// borrar todas las versiones
for (int i = 1; i <= biggerVersion; i++) {
String versionKey = clave + "::v" + i;
client.delete(versionKey).get();
}
// borrar el contador
client.delete(clave + "_version").get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
cliente.eliminar(llave);

 

Utilizar el control de versiones

Como ejemplo, he creado una pequeña biblioteca disponible en GitHub https://github.com/tgrall/couchbase-how-to-versioningEsta librería extiende el cliente Couchbase y sobreescribe algunas de las operaciones: set, replace y delete. (la basica: sin TLL, sin durabilidad) Como dije antes esto es solo un ejemplo.
Construir e instalar 
git clone https://github.com/tgrall/couchbase-how-to-versioning.git
cd cómo-versionar
mvn clean install
A continuación, añada esta biblioteca a su proyecto además de Couchbase Java Client, por ejemplo en su pom.xml

com.couchbase.howtos
couchbase-cómo-versionar
1.0-SNAPSHOT

couchbase
couchbase-client
1.1.8

Codifique su aplicación

Crear un documento y versionarlo:

 Lista uris = nueva LinkedList();
uris.add(URI.create("http://127.0.0.1:8091/pools"));
CouchbaseClientWithVersioning cliente = null
intentar {
client = new CouchbaseClientWithVersioning(uris, "default", "");
Cadena clave = "clave-001";
client.set(key, "Esta es la versión original");
System.out.printf("Original '%s' .n", client.get(key));
client.set(key, "Esta es una nueva versión", true); // crear una nueva versión
System.out.printf("Versión actual '%s' .n", client.get(key));
System.out.printf("Versión 1 '%s' .n", client.get(key, 1));
client.set(key, "Esta es otra versión", true); // crear una nueva versión
System.out.printf("Todas las versiones %s .n", client.getAllVersions(key));
client.deleteVersion(key, 1); // crear una nueva versión
System.out.printf("Todas las versiones %s (después de eliminar 1 versión).n", client.getAllVersions(key));
client.delete(key); // crear una nueva versión
System.out.printf("Todas las versiones %s (después de borrar la clave principal).n", client.getAllVersions(key));
} catch (Exception e) {
e.printStackTrace();
}
if (cliente !=null) {
client.shutdown();
}

Explicación rápida:

  • Línea 5: en lugar de utilizar CouchbaseClientla aplicación utiliza la extensión  CouchbaseClientWithVersioning clase.
  • Línea 7: crear una nueva entrada
  • Línea 9: crear una nueva versión, el valor booleano a "true" fuerza el versionado del documento
  • La aplicación utiliza otros métodos como obtener una versión específica (línea 11), obtener todas las versiones (línea 13), borrar una versión específica (línea 14), y finalmente borrar la clave y todas las versiones (línea 16).
Así que usando este enfoque el desarrollador controla explícitamente cuando crear una versión, ya que tiene que añadir el parámetro booleano en la operación set. En esta pequeña librería de ejemplo también es posible hacer auto versionado, en este caso todas las llamadas a set y replace crearán una versión, para conseguirlo el desarrollador sólo tiene que llamar al método setAutoVersioning(true). Algo como
    client = new CouchbaseClientWithVersioning(uris, "default", "");
client.setAutomaticVersionning(true);

 

Con este enfoque puedes proporcionar versionado a tu aplicación con un cambio mínimo de código. Puede probarlo en la aplicación Beer Sample, simplemente no olvide cambiar las vistas como documenter arriba para que sólo devuelvan actual versión de los documentos.

Conclusión

Como puedes ver hacer versionado en Couchbase no es tan complicado, pero es algo que debe hacer tu aplicación en base a sus requerimientos y restricciones. Tienes muchas soluciones diferentes y ninguna de estas opciones es perfecta para todos los casos de uso.

En este código de ejemplo específico, estoy trabajando con un diseño simple donde creo una copia de los documentos para cada versión. Con este enfoque también, es interesante mencionar que se puede versionar "cualquier cosa", no sólo documento JSON sino también cualquier valor. Como he dicho antes, este es un enfoque posible, y como cualquier diseño, tiene algún impacto en la aplicación o base de datos, en este caso la mayoría de la base de datos:

  • Aumentar el número de llaves y documentos
  • Duplicar -o más- el número de operaciones, por ejemplo al actualizar un documento, la aplicación necesita obtener el valor actual, crear una versión, guardar la versión actual.
  • Gestión de la coherencia al añadir una nueva versión e incrementar el número de versión (es necesario tratar los errores al crear una nueva versión, eliminar las versiones y contra....).
Se le podrían añadir muchas funciones fácilmente, por ejemplo:
  • Limitar a un número determinado de versiones,
  • Habilitar el versionado sólo de la operación replace()
  • Añadir atributo específico sobre versiones en documento JSON (por ejemplo fecha de la versión)
  • ….

Si estás usando versionado en tu aplicación Couchbase, siéntete libre de comentar o escribir un pequeño artículo que describa la forma en que lo estás haciendo.

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por El equipo de Couchbase

Jennifer Garcia es Gerente Senior de Web en Couchbase Inc. Como responsable del sitio web, Jennifer tiene la responsabilidad general de las propiedades del sitio web, incluido el diseño, la implementación, el contenido y el rendimiento.

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.