Buenas prácticas y tutoriales

Almacenamiento, indexación y búsqueda de archivos con Couchbase y Spring Boot

He estado queriendo mostrar la mayoría de las nuevas características de búsqueda de Couchbase disponibles en 4.5 en un simple proyecto. Y ha habido cierto interés recientemente sobre almacenamiento de archivos o binarios en Couchbase. Desde una perspectiva general y genérica, las bases de datos no están hechas para almacenar archivos o binarios. Normalmente lo que harías es almacenar archivos en un almacén binario y sus metadatos asociados en la BD. Los metadatos asociados serán la localización del archivo en el almacén binario y tanta información como sea posible extraída del archivo.

Así que este es el proyecto que os mostraré hoy. Es una aplicación Spring Boot muy simple que permite al usuario subir archivos, almacenarlos en un almacén binario, donde el texto asociado y los metadatos se extraen del archivo, y le permiten buscar archivos basados en los metadatos y el texto. Al final podrás buscar archivos por mimetype, tamaño de imagen, contenido de texto, básicamente cualquier metadato que puedas extraer del archivo.

La tienda binaria

Esta es una pregunta que nos hacen a menudo. Ciertamente se pueden almacenar datos binarios en una BD, pero los ficheros deben estar en un almacén binario apropiado. Decidí crear una implementación muy simple para este ejemplo. Básicamente hay una carpeta en el sistema de archivos declarada en tiempo de ejecución que contendrá todos los archivos cargados. Un resumen SHA1 se calculará a partir del contenido del archivo y se utilizará como nombre de archivo en esa carpeta. Obviamente podrías usar otros almacenes binarios más avanzados como Manta de Joyent o Amazon S3 por ejemplo. Pero vamos a mantener las cosas simples para este post :) He aquí una descripción de los servicios utilizados.

Servicio SHA1

Este es el más simple, con un método que básicamente devuelve un resumen SHA-1 basado en el contenido del archivo. Para simplificar el código aún más estoy usando Apache commons-codec:

Servicio de extracción de datos

Este servicio sirve para extraer metadatos y texto de los archivos subidos. Hay muchas formas diferentes de hacerlo. Yo he optado por ExifTool y Poppler.

ExifTool es una gran herramienta de línea de comandos para leer, escribir y editar metadatos de archivos. También puede generar metadatos directamente en JSON. Y por supuesto no se limita al estándar Exif. Es compatible con una amplia variedad de formatos. Poppler es una biblioteca de utilidades PDF que me permitirá extraer el contenido de texto de un PDF. Como se trata de herramientas de línea de comandos, utilizaré plexus-utils para facilitar las llamadas CLI.

Existen dos métodos. El primero es extraerMetadatos y es responsable de la extracción de metadatos de ExifTool. Equivale a ejecutar el siguiente comando:

En -n está aquí para asegurarse de que todos los valores numéricos se darán como números y no como cadenas y -json para asegurarse de que la salida está en formato JSON. Esto puede darle una salida como esta:

Hay algunas informaciones interesantes como el tipo mime, el tamaño, la fecha de creación y más. Si el tipo mime del archivo es aplicación/pdf entonces podemos intentar extraer texto de él con poppler, que es lo que hace el segundo método del servicio. Es equivalente a la siguiente llamada CLI:

Este comando envía el texto extraído a la salida estándar. Que podemos recuperar y poner en un texto completo en un objeto JSON. Código completo del servicio a continuación:

Cosas bastante simples como se puede ver una vez que utilice plexus-utils.

BinaryStoreService

Este servicio es responsable de ejecutar la extracción de datos y almacenar archivos, eliminarlos o recuperarlos. Empecemos por la parte de almacenamiento. Todo ocurre en el storeFile método. Lo primero que se hace es recuperar el digest del fichero, y luego escribirlo en la carpeta de almacenamiento binario declarada en la configuración. Una vez que el archivo está escrito, se llama al servicio de extracción de datos para recuperar los metadatos como un JsonObject. A continuación, la ubicación del almacén binario, el tipo de documento, el resumen y el nombre del archivo se añaden a ese objeto JSON. Si el archivo cargado es un PDF, se llama de nuevo al servicio de extracción de datos para recuperar el contenido de texto y almacenarlo en un objeto texto completo campo. A continuación se crea un JsonDocument con el digest como clave y el JsonObject como contenido.

Leer o borrar debería ser bastante sencillo de entender ahora:

Tenga en cuenta que se trata de una aplicación muy ingenua.

Indexación y búsqueda de archivos

Una vez que haya cargado los archivos, querrá recuperarlos. La primera forma muy básica de hacerlo sería mostrar la lista completa de archivos. Entonces podrías usar N1QL para buscarlos basándote en sus metadatos o FTS para buscarlos basándote en su contenido.

Servicio de búsqueda

getFiles simplemente ejecuta la siguiente consulta: SELECT binaryStoreLocation, binaryStoreDigest FROMpor defectoWHERE type= 'archivo'. Esto envía la lista completa de archivos subidos con su compendio y la ubicación del almacén binario. Observe que la opción de coherencia está establecida en declaración_plus. Es una aplicación de documentos, así que prefiero una coherencia fuerte.

A continuación tiene búsquedaN1QLArchivos que ejecuta una consulta N1QL básica con una cláusula WHERE adicional. Así que por defecto es la misma consulta anterior con una parte adicional WHERE. Hasta ahora no hay una integración más estrecha. Podríamos tener un elegante formulario de búsqueda que permitiera al usuario buscar archivos basándose en sus tipos mime, tamaño o cualquier otro campo dado por ExifTool.

Y por último tiene buscarArchivosDeTextoCompleto que toma un String como entrada y lo utiliza en un Partido consulta. A continuación, se devuelve el resultado con fragmentos de texto en los que se ha encontrado el término. Este fragmento permite destacar el término en su contexto. También pido el binaryStoreDigest y binaryStoreLocation campos. Son los que se utilizan para mostrar los resultados al usuario.

En TermQuery.on define qué índice estoy consultando. Aquí está definido como 'file_fulltext'. Significa que he creado un índice de texto completo con ese nombre:

Juntarlo todo

Configuración

Unas palabras sobre la configuración. Lo único configurable hasta ahora es la ruta del almacén binario. Como estoy usando Spring Boot, sólo necesito el siguiente código:

Con eso simplemente puedo añadir binaryStore.root=/Usuarios/ldoguin/binaryStore a mi aplicación.propiedades archivo. También quiero permitir la carga de archivos de 512 MB como máximo. Además, para aprovechar la autoconfiguración de Spring Boot Couchbase, necesito añadir la dirección de mi servidor Couchbase. Al final mi aplicación.propiedades se ve así:

Usar la autoconfiguración de Spring Boot simplemente requiere tener spring-boot-starter-parent como padre y Couchbase en el classpath. Así que sólo es cuestión de añadir una dependencia java-client de Couchbase. Estoy especificando la versión 2.2.4 aquí porque por defecto es 2.2.3 y FTS sólo está en 2.2.4. Puedes echar un vistazo al archivo pom completo en Github. Felicitaciones a Stéphane Nicoll de Pivotal y Simon Baslé de Couchbase para esta maravillosa integración con Spring.

Controlador

Como esta aplicación es muy sencilla, he puesto todo bajo el mismo controlador. El punto final más básico es /archivos. Muestra la lista de archivos ya cargados. Sólo una llamada al searchService, poner el resultado en la página Modelo y luego renderizar la página.

Utilizo Hoja de tomillo para renderizar y Interfaz semántica como framework CSS. Puede echar un vistazo a la plantilla utilizada aquí. Es la única plantilla utilizada en la aplicación.

Una vez que tenga una lista de archivos, puede descargarlos o eliminarlos. Ambos métodos están llamando al método del servicio de almacenamiento binario, el resto del código es el clásico Spring MVC:

Obviamente también querrás subir algunos archivos. Es un simple Multipart POST. Se llama al servicio de almacenamiento binario, persiste el archivo y extrae los datos apropiados, luego redirige al servicio /archivos punto final.

Los dos últimos métodos se utilizan para la búsqueda. Simplemente llaman al servicio de búsqueda y añaden el resultado al Modelo de página y lo renderizan.

Y esto es más o menos todo lo que necesitas para almacenar, indexar y buscar archivos con Couchbase y Spring Boot. Es una aplicación simple y hay muchas, muchas otras cosas que podrías hacer para mejorarla, empezando por un formulario de búsqueda adecuado que exponga los campos extraídos de ExifTool. Múltiples cargas de archivos y arrastrar y soltar sería un buen plus. ¿Qué más te gustaría ver? Háznoslo saber en los comentarios.

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

Autor

Publicado por Laurent Doguin

Laurent es un metalero empollón que vive en París. Principalmente escribe código en Java y texto estructurado en AsciiDoc, y a menudo habla sobre datos, programación reactiva y otras cosas de moda. También fue Developer Advocate de Clever Cloud y Nuxeo, donde dedicó su tiempo y experiencia a ayudar a esas comunidades a crecer y fortalecerse. Ahora dirige las relaciones con los desarrolladores en Couchbase.

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.