Couchbase y XML: ¡sin problemas!

Lo he oído decir docenas de veces: "Oye, Couchbase es genial pero yo uso XML".

Reconozco que rebatir con "Couchbase puede ser tu base de datos XML" es bastante atrevido, especialmente para una base de datos de documentos orientada a JSON. Puede que algunos miembros de la comunidad de Couchbase se lo tomen a mal, pero espero que entiendas lo que quiero decir al final de este post.

Es un hecho que muchas aplicaciones heredadas todavía dependen de XML, pero ¿es Couchbase realmente la solución adecuada para almacenar y procesar tus datos XML? No te preocupes: con respecto a Couchbase y XML puedes tener tu pastel y comértelo también.

Después de introducir algunos conceptos, este artículo te muestra cómo convertir automática e instantáneamente XML en equivalentes JSON dentro de Couchbase con casi cero esfuerzo - todo a través de una función Eventing. Si sólo piensas en JSON como el formato informático intermedio que se utiliza para almacenar tu XML, puede que ya veas a dónde me dirijo.

Cuando transformas tus datos XML en una representación JSON nativa, aprovechas el rico ecosistema de servicios de Couchbase, que incluye N1QLIndexación, Búsqueda de texto completo, Eventosy Analítica.

Couchbase es una base de datos creada específicamente para que la adaptes a tus necesidades. ¿Sólo necesitas una caché rápida? Sólo necesita el servicio de datos o el almacén de valores clave. ¿Desea un acceso de tipo SQL? Añada los servicios de consulta e índice. ¿O tal vez necesite Analytics o Full-Text Search? Sólo tiene que añadir algunos nodos del tipo adecuado.

Cada uno de los servicios anteriores escala de forma independiente para que acabes construyendo, y lo que es más importante, pagando por - sólo lo que necesitas. En el siguiente artículo, utilizo Eventing para transformar Couchbase en una base de datos compatible con XML. Sé que suena demasiado bien para ser verdad, pero créeme que realmente funciona.

Si está familiarizado con Couchbase, XML y JSON, no dude en pase a la sección Requisitos previos.

El modelo de datos de Couchbase

Servidor Couchbase es una plataforma de datos distribuidos de código abierto. Almacena datos como artículoscada uno de los cuales tiene un clave y un valor. Las operaciones de datos en menos de un milisegundo se realizan mediante potentes servicios de consulta e indexación, así como un lenguaje de consulta orientado a documentos y repleto de funciones, N1QL. Múltiples instancias de Couchbase Server pueden combinarse en una sola. grupo.

Claves

Cada valor (binario o JSON) se identifica mediante una clave única, definida por el usuario o la aplicación al guardar el elemento. La clave es inmutable: una vez guardado el ítem, la clave no puede ser cambiada. Ten en cuenta que Couchbase también se refiere a la clave de un ítem como su id.

Cada llave:

    • Debe ser una cadena UTF-8 sin espacios. Los caracteres especiales, como (, %, /, " y _ son aceptables.
    • No puede superar los 250 bytes.
    • Debe ser único dentro de su cubo.

Valores

El tamaño máximo de un valor es de 20 MiB. Un valor puede ser:

    • Binario: Se acepta cualquier forma de binario. Tenga en cuenta que un valor binario no se puede analizar, indexar ni consultar. Sólo se puede recuperar por clave.
    • JSON: Un valor JSON, denominado documentopueden ser analizados, indexados y consultados. Cada documento consta de uno o varios atributos, cada uno de los cuales tiene su propio valor. El valor de un atributo puede ser de tipo básico -como un número, una cadena o un booleano- o complejo, como un documento incrustado o una matriz.

JSON es la base de datos

Hablemos más sobre JSON. Puedes analizar, indexar, consultar y manipular documentos JSON. De hecho, Couchbase introdujo el lenguaje de consulta N1QL (pronunciado "nickel") para satisfacer las necesidades de consulta de las bases de datos distribuidas orientadas a documentos. N1QL se utiliza para manipular los datos JSON en Couchbase, igual que SQL manipula los datos en una base de datos relacional (RDBMS). Dispone de SELECCIONE, INSERTAR, ACTUALIZACIÓN, BORRAR y FUSIONAR para operar con datos JSON.

Podrías almacenar XML como una cadena o como un bloque binario, pero ¿dónde está la gracia o la utilidad? ¿Por qué no convertir automáticamente el XML en JSON? Me alegro de que lo preguntes.

XML: Lenguaje de marcado extensible

XML es un lenguaje de marcado introducido en 1996 que define un conjunto de reglas para codificar documentos en un formato legible tanto por humanos como por máquinas. Es una recomendación del Consorcio World Wide Web (W3C).

Los objetivos de diseño de XML hacen hincapié en la simplicidad, la generalidad y la facilidad de uso en Internet. Se trata de un formato de datos textuales con fuerte soporte a través de Unicode para diferentes lenguajes humanos. Aunque el diseño de XML se centra en los documentos, el lenguaje se utiliza ampliamente para la representación de estructuras de datos arbitrarias, como las empleadas en los servicios web.

He aquí un ejemplo de XML:

JSON: Notación de objetos de JavaScript

Creado hacia 2001, JSON es un formato de archivo estándar abierto bastante ligero y un formato de intercambio de datos que utiliza texto legible por humanos para almacenar y transmitir objetos de datos consistentes en pares atributo-valor y matrices (u otros valores serializables).

JSON es un formato de datos muy común, con una diversa gama de aplicaciones, un ejemplo son las aplicaciones web que se comunican con un servidor.

He aquí una muestra de JSON:

JSON se ha apoderado del mundo

Hoy en día, cuando dos aplicaciones cualesquiera se comunican entre sí a través de Internet, lo más probable es que lo hagan utilizando JSON, especialmente si se comunican en texto legible por humanos.

JSON vs XML adoption

Si eres un fan de XML, no dispares al mensajero aquí. Estoy seguro de que XML nunca desaparecerá, dado que HTML es un lenguaje de marcado, pero me gusta pensar que las estadísticas no mienten cuando se trata de desarrollar aplicaciones de Internet que necesitan comunicarse entre sí.

Requisitos previos: Aprendizaje del concurso completo

En este artículo vamos a utilizar la última versión de Couchbase - versión 6.6.2 - sin embargo, debería funcionar bien en versiones anteriores también.

Si no estás familiarizado con Couchbase o el servicio Eventing, por favor, consulta los siguientes recursos, incluyendo al menos un ejemplo de Eventing:

Inserción de XML en Couchbase

Ahora deberías tener una aplicación que cargue datos, o puede que hayas utilizado cbimport para cargar tus datos XML en tu cluster Couchbase.

En el código siguiente, cargo mi primer documento con una etiqueta clave xml::1 y un cuerpo consistente en un tipo y el id utilizados en la clave (estos valores son opcionales pero útiles) y, por último, una propiedad in_xml que contiene la propia cadena XML.

No podemos hacer demasiado con la cadena XML anterior. Claro, podríamos indexar la propiedad in_xml como cadena, pero no obtendremos mucho rendimiento haciendo esto a menos que utilicemos una búsqueda por prefijo, que en mi humilde opinión, lo más probable es que no sirva para nada.

Podríamos pasarlo al producto Full-Text Search (FTS). En este caso, obtendría más utilidad, pero tendría que indexar toda la carga útil XML (no sólo algo importante).

Lo que realmente queremos es la representación JSON de la propiedad XML string in_xmlquizás algo como:

Utilización de la nueva propiedad out_jsonAhora vemos las propiedades JSON individuales en una estructura adecuada: algo con lo que N1QL, Indexación, Búsqueda de Texto Completo (FTS), Eventos y Análisis trabajan de forma nativa y eficiente.

Con estos pasos preliminares tras nosotros, podrías pensar en simplemente parsear tus datos y transformarlos a JSON antes de ponerlos en Couchbase. Pero el inconveniente es que ahora tenemos más equipaje que transportar y más infraestructura (fuera de Couchbase) que desplegar a medida que escalamos añadiendo más nodos.

Si podemos evitarlo, no queremos escribir un analizador sintáctico personalizado. Eso no es divertido, y es difícil de mantener como sus requisitos y formatos de datos cambian con el tiempo.

Lo ideal es una solución en el servidor que convierta genéricamente XML a JSON en tiempo real sin afectar a los cargadores de datos.

Conversión de XML a JSON sobre la marcha

Introduzca el servicio de eventos de Couchbase.

Piense en Eventing como un "post trigger" en un documento que responde a cada cambio (o mutación) en sus datos. La idea principal es que cada vez que inserte o actualice su documento (consulte xml::1 arriba) un pequeño fragmento de JavaScript, o lambda, se ejecuta contra el documento y encapsula la lógica de negocio necesaria para manipular el documento y asegurarse de que el documento está en el formato deseado.

En este caso, queremos convertir un documento como el siguiente:

En tiempo real, queremos convertir el documento anterior en un documento enriquecido como el siguiente:

El documento enriquecido que se muestra arriba se puede buscar mediante clave-valor o mediante un índice en cualquier campo determinado utilizando N1QL.

Al igual que antes, vemos las propiedades JSON individuales en una estructura adecuada, pero bajo la etiqueta out_json que permite utilizar eficazmente la búsqueda de texto completo (FTS), los análisis e incluso otras funciones de Eventing.

Función: convertXMLtoJSON

Eventing le permite escribir lógica de negocio pura y el servicio Eventing se encarga de toda la infraestructura necesaria para gestionar y escalar su función (horizontal y verticalmente) a través de múltiples nodos de una manera performante y fiable.

Todas las funciones de Eventing tienen dos puntos de entrada OnUpdate(doc,meta) y OnDelete(meta,opciones). Tenga en cuenta que en este ejemplo no nos preocupa este último punto de entrada.

Cuando un documento cambia o muta (insertar, upsert, reemplazar, etc.) una copia del documento y algunos metadatos sobre el documento se pasarán a un pequeño punto de entrada de JavaScript OnUpdate(doc,meta):

En OnUpdate(doc,meta) lógica anterior realiza cuatro pasos en cualquier mutación.

    • En primer lugar, el prefijo del clave si no empieza por xml:no hacemos nada más. Tenga en cuenta que meta.id es el clave del doc.
    • En segundo lugar, simplemente llamamos a una función parseXmlToJson(doc.in_xml) donde simplemente pasamos la cadena XML a la función.
    • En tercer lugar, lo que vuelve se añade como un nuevo campo a la copia del documento como la propiedad out_json.
    • En cuarto lugar, actualizamos el documento en tiempo real con la representación JSON.

El núcleo de la lógica de conversión de XML a JSON

Esta es la lógica central para la conversión de XML a JSON:

Gracias al usuario Pieza maestra en Stack Overflow por compartir el método parseXmlToJson(xml) con el mundo. El método utiliza una expresión regular genial sobre la cadena XML y devuelve un objeto JSON de primera clase. (Sí, funciona y es a la vez elegante y compacto.)

Tenga en cuenta que en Couchbase 7.0 el método MatchAll(str, regExp) en nuestro código JavaScript anterior es no necesario porque Couchbase ahora tiene un corredor v8 más actual que incluye el String.prototype.MatchAll() función.

Optimicemos la función Eventing

Lo que tenemos hasta ahora funciona bien, pero hay un problema.

Suponga que sus datos tienen 100.000 mutaciones por segundo, todas con un clave prefijo de xml:. Aunque el in_xml nunca cambia, nuestra función Eventing actual a) realizará 100.000 conversiones de XML a JSON y b) realizará 100.000 escrituras en el servicio de datos (o almacén de valores clave). Además, lo más probable es que tu XML sea mucho más complejo que nuestro ejemplo in_xml y puede tener un anidamiento profundo y miles de campos.

Algunas reflexiones que debemos tener en cuenta:

    • Convertir un documento XML grande y anidado mediante una rutina recursiva requiere recursos informáticos. El método parseXmlToJson(xml) se ejecutará en cada mutación aunque el XML no haya cambiado.
    • Escribir en bases de datos implica E/S, y queremos ahorrar ciclos o escrituras para trabajos más importantes. Con la función Eventing actual, realizaremos una escritura o actualización del documento en el almacén de valores clave en cada mutación, incluso si el XML no ha cambiado.

Para solucionar los problemas anteriores, vamos a añadir un poco de lógica para actualizar sólo la propiedad del documento out_xml si el in_xml cambios de datos o si no tenemos ya un out_xml propiedad.

Para llevar a cabo esta optimización, utilizaremos un suma de comprobación a través de Eventing's fast crc64() en el in_xml y almacenarlo en nuestro documento como una propiedad: xmlchksum.

Podemos entonces utilizar este campo para minimizar el trabajo extra de convertir innecesariamente XML a JSON o escribir innecesariamente un documento sin cambios en el servicio de datos.

Aquí está la optimización:

Esto es lo que hemos añadido al original OnUpdate(doc,meta) punto de entrada.

    • En primer lugar, calculamos un suma de comprobación en la cadena XML a la que se accede desde doc.in_xml.
    • En segundo lugar, lo comparamos con un suma de comprobación: doc.xmlchksum (si existe).
    • En tercer lugar, si el suma de comprobación falta o difiere, convertimos el XML en JSON y almacenamos tanto el nuevo suma de comprobación xmlchksum y el out_json propiedades en el documento escribiéndolo de nuevo al Servicio de Datos.

La función final completa

Aquí está nuestra función completa Eventing para convertir XML a JSON con todas las optimizaciones antes mencionadas:

Despliegue de la función de eventos

Ahora es el momento de desplegar la función Eventing. Hemos revisado un poco el código y el diseño del traductor de XML a JSON, y ahora es el momento de ver cómo funciona todo junto.

En este punto, tenemos una función en JavaScript así que necesitamos añadirla a tu cluster de Couchbase y desplegarla en un estado activo.

Este ejemplo requiere dos cubos: fuente (es decir, su almacén de documentos) y metadatos (es decir, un bloc de notas para Eventing que puede compartirse con otras funciones de Eventing). El sitio fuente debe tener un tamaño de al menos 100 MB (si desea realizar pruebas con más de 10 millones de documentos, es posible que desee hacer que el archivo fuente cubo más grande). El metadatos debe tener un tamaño mínimo de 100 MB. Ambos cubos deben existir ya como según los requisitos previos anteriores.

    • Verifique la configuración actual de su cubo accediendo a la página Consola Web de Couchbase > Cubos página:The Couchbase Web Console Buckets page

Añadir manualmente la función convertXMLtoJSON

Para añadir la primera función de Eventing desde Consola Web de Couchbase > Eventos haga clic en AÑADIR FUNCIÓNpara añadir una nueva función. La dirección AÑADIR FUNCIÓN Aparece entonces el diálogo

En el AÑADIR FUNCIÓN diálogo, facilite la siguiente información para cada uno de los elementos de la función:

      • Para el Cubo de origen en el menú desplegable fuente.
      • Para el Cubo de metadatos en el menú desplegable metadatos.
      • Asegúrese de que convertXMLtoJSON es el nombre de la función que se está creando en el directorio Nombre de la función cuadro de texto.
      • [Paso opcional] Introduzca el texto Conversión XML genéricaen el Descripción cuadro de texto.
      • Para el Ajustes utilice los valores por defecto.
      • Para el Fijaciones crear dos enlaces:
        • Para la encuadernación, el alias de cubo, especifica src_bkt como el nombre de alias del cubo y seleccione fuente como cubo asociado, y el modo debe ser leer y escribir.
        • Una vez configurados los ajustes, el diálogo debería tener este aspecto:
          Couchbase add function dialogue box
        • Tras facilitar toda la información requerida en el AÑADIR FUNCIÓN pulse Siguiente Añadir código. En cron_impl_2func_651 aparece el diálogo. La dirección convertXMLtoJSON contiene inicialmente un bloque de código de marcador de posición. Tendrá que sustituir el código JavaScript que hemos desarrollado en este bloque.
        • convert XML to JSON with Couchbase Eventing
        • Copie el siguiente código fuente JavaScript de la función Eventing (48 líneas) y péguelo en el bloque de código del marcador de posición de convertXMLtoJSON:
        • Después de pegar, aparece la pantalla que se muestra a continuación:The function editor in Couchbase Eventing
        • Haga clic en Guardar.
        • Para volver a la pantalla de Eventos, pulse el botón < volver a Concurso completo (debajo del editor) o haga clic en el enlace Eventos opción.

Despliegue de la función

Ahora estamos listos para iniciar las funciones de Eventing. Desde el Consola Web de Couchbase > Eventos siga estos pasos:

        • Haga clic en el nombre de la función convertXMLtoJSON para expandir y exponer los controles de función.Eventing function controls
        • Haga clic en Despliegue.
        • En el Confirmar función de despliegue seleccione Función de despliegue de la opción Límite de alimentación.
          Confirm deploy function Couchbase
        • El despliegue de su función tardará unos 18 segundos en activarse.

Probar la función de marcha

En este punto tenemos una lambda en ejecución que actualizará cualquier documento con una etiqueta clave prefijo de xml: y una propiedad XML de in_xml.

Para ejercitar la función Eventing convertXMLtoJSONvaya a la página Documentos en la interfaz de usuario y haga lo siguiente:

        • Haga clic en AÑADIR DOCUMENTO.
        • Introduzca un clave de xml::1 (asegúrese de que el prefijo es xml:)
        • Haga clic en Guardar.
        • Introduzca un cuerpo como sigue:
        • Haga clic en Guardar.
        • Edite el documento que acaba de guardar; observará que se ha actualizado en tiempo real
        • Ajuste el in_xml. Quizás añadir FEBRERO</MES antes del título.
        • Haga clic en Guardar.
        • De nuevo, edite el documento que acaba de guardar. Verás que se ha vuelto a actualizar en tiempo real:
        • Añade una nueva propiedad arriba tipocomo "otro": "esto es divertido",
        • Haga clic en Guardar.
        • Una vez más, edite el documento. Tenga en cuenta que el suma de comprobación no se actualizará

Procesemos 100.000 registros XML

Ahora que ya has visto cómo funcionan las cosas, vamos a volcar un montón de datos en la función. En primer lugar, tenemos que generar algunos datos.

        • Utilizaré un sencillo script Perl llamado xml_data_gen.pl que escribí para esta entrada del blog:
        • Para probar el script generador anterior xml_data_gen.pl simplemente corre: ./xml_data_gen.pl --blk 1 --num 5
        • Deberías ver algo como:
        • Para crear un registro de 100K xml_data_gen.pl para después cargarlo en tu cluster de Couchbase sólo tienes que ejecutarlo: ./xml_data_gen.pl --blk 1 --num 100000 > data.json
        • Ahora tenemos que cargar los datos. Utilizaré la función cbimport situado en la ./bin de tu instalación de Couchbase en uno de tus nodos. Asumo que tienes acceso shell a tu cluster de Couchbase y las credenciales requeridas.
        • Eche un vistazo. Todos los artículos 100K se habrán convertido instantáneamente a medida que se cargan (en la mutación causada por la inserción).

Si quieres más rendimiento, puedes escalar verticalmente aumentando el número de trabajadores en la configuración de funciones o añadiendo más nodos Eventing. Si quieres cargar más datos y mantener la residencia de memoria 100%, puede que necesites aumentar el tamaño de tu bucket.

Reflexiones finales

Espero que esta guía te haya resultado instructiva y que hayas aprendido a apreciar mejor el el servicio de eventos Couchbase en su conjunto.

Antes optimizábamos la Función para utilizar menos recursos de computación. También podríamos optimizar el espacio de almacenamiento. Tenga en cuenta que tenemos tanto un in_xml y un out_json en nuestros documentos después de enriquecerlos. Con un pequeño retoque (añadiendo dos líneas) podríamos eliminar la propiedad in_xml y eliminar el almacenamiento redundante (me ahorra 30% de espacio en disco). He optado por dejar esto fuera del ejemplo para resaltar mejor cómo se ejecutaba la función, pero te invito a que experimentes tú mismo con ella utilizando lo siguiente:

He colocado este ejemplo en el sitio principal de documentación de Couchbase como el ejemplo Scriptlet: Función: convertXMLtoJSON. No traducirá los atributos XML, pero eso fue fácil de añadir (véase el párrafo siguiente). Sin embargo, el método simple parseXmlToJson() que utilicé se ajustaba perfectamente a los datos iniciales.

Durante el desarrollo, empecé de forma sencilla y probé algunos documentos XML masivos pero, por supuesto, puede que no haya cubierto toda la gama de construcciones XML. Desarrollé el segundo Scriptlet convertAdvXMLtoJSON (que no aparece en este artículo), ya que enseguida descubrí que muchos documentos XML utilizan atributos y tienen algunas variantes sintácticas interesantes.

Esto me llevó a crear una función Eventing más extensa que traduce atributos XML y las variantes de sintaxis que encontré. También encontrarás la fuente de esta función Eventing más larga y capaz en el sitio de documentación principal de Couchbase como el Scriptlet de ejemplo: Función: convertAdvXMLtoJSON. Esta versión más avanzada ha convertido con éxito documentos XML de gran tamaño, incluidos "archivos de geometría de OpenStreetmap" y también "mediciones operativas celulares de Huawei".

Te reto a que pruebes a hacer lo siguiente:

        • Escribe una función inversa: En lugar de convertXMLtoJSON, digamos convertJSONtoXML
        • Alter convertAdvXMLtoJSON para anteponer cualquier nombre de propiedad como atr_ para ayudarle a identificar los atributos XML en la conversión final a JSON.
        • Añadir un mapa JavaScript opcional y una rutina para convertir genéricamente las propiedades por nombre en números reales y booleanos (en lugar del tipo de cadena predeterminado).
        • Implementar una mejora para aplicar una "Document Type Definition" o DTD a los datos de entrada, donde se lee la DTD de otro documento.
        • Crear un traductor para que las consultas XPath se dirijan (apunten) a diferentes partes de una representación JSON del documento convertido.

No olvides experimentar con SQL++ (N1QL) en el Query Workbench y utilizar el Index Advisor para consultar y crear índices óptimos para acceder a tus datos XML (transformados a JSON).

Recursos

Referencias

Espero haberte convencido de que Couchbase via Eventing es una base de datos XML.

Me encantaría que me contaras qué te han parecido las capacidades de Couchbase y Eventing y cómo benefician a tu negocio de cara al futuro. Por favor, comparte tu opinión a través de los comentarios de abajo o en los foros de Couchbase.

 

Autor

Publicado por Jon Strabala, Director Principal de Producto, Couchbase

Jon Strabala es Gerente Principal de Producto, responsable del Servicio de Eventos de Couchbase. Antes de unirse a Couchbase, pasó más de 20 años construyendo productos de software a través de diversos dominios, comenzando con EDA en el sector aeroespacial y luego la transición a la construcción de software empresarial centrado en lo que hoy se conoce como "IoT" y "datos a escala". Jon trabajó para varias pequeñas consultoras de software hasta que finalmente fundó y dirigió su propia empresa. Tiene una amplia experiencia en NoSQL/NewSQL, tanto en la contribución como en la comercialización de nuevas tecnologías como los mapas de bits comprimidos y los almacenes de columnas. Jon es licenciado en ingeniería eléctrica y tiene un máster en ingeniería informática, ambos por la Universidad del Sur de California, y un MBA por la Universidad de California en Irvine.

Dejar una respuesta