Ruby on Rails es a menudo el framework elegido para poner en marcha nuevos proyectos. La velocidad de desarrollo e iteración es en muchos sentidos incomparable. Como tal, tal vez usted desea utilizar Rails como el marco para su aplicación que requiere una gran flexibilidad en los datos y tiene una estructura fluida. Tal vez esté creando una aplicación de Internet de las Cosas o un sistema de gestión de contenidos que deba manejar todo tipo de datos. Las soluciones tradicionales de bases de datos para Rails no son suficientes. ¿Qué hay que hacer?
En esta guía, descubrirás las consideraciones y pasos a seguir para utilizar Couchbase como tu base de datos totalmente integrada en tu aplicación Rails. La decisión de construir con Couchbase no sólo introduce cambios técnicos de implementación, sino también cambios conceptuales en la forma de enfocar tus datos. Vamos a sumergirnos en ellos.
tl;dr ¿Interesado sólo en ver código? Echa un vistazo a un ejemplo real de aplicación completamente construida demostrando todas las acciones CRUD con Ruby on Rails y el ORM Ruby de Couchbase en GitHub.
Modelo documental frente a modelo relacional
En Rails estamos acostumbrados a trabajar con un modelo relacional, normalmente utilizando ActiveRecord. Los datos se organizan en tablas con filas y columnas, y las relaciones entre entidades se definen mediante claves externas. Couchbase, en cambio, utiliza un modelo documental, en el que los datos se almacenan en documentos JSON.
El modelo de documento permite una mayor flexibilidad en las estructuras de datos. Por ejemplo, ahora es posible almacenar datos anidados directamente en el mismo documento de los datos principales. Esto significa que si estás construyendo una plataforma de blogs, los comentarios de los artículos se pueden añadir directamente en el documento JSON de cada artículo, en lugar de asociar los comentarios a los artículos por el ID del comentario. La decisión de utilizar o no esta posibilidad depende de los patrones de acceso y de las consideraciones de rendimiento que debes tener en cuenta a la hora de diseñar tu aplicación.
La diferencia en los datos se verá como en los siguientes ejemplos.
Comentarios incrustados:
1 2 3 4 5 6 7 8 |
{ "título: "Mi artículo", "contenido": "Este es el contenido del artículo...", "comentarios": [ {"autor": "Usuario1", "texto": "¡Gran artículo!"}, {"autor": "Usuario2", "texto": "Gracias por la información".} ] } |
Mientras que el modelo tradicional con el que la mayoría de desarrolladores Rails están familiarizados tiene este aspecto:
1 2 3 4 5 |
{ "título: "Mi artículo", "contenido": "Este es el contenido del artículo...", "comment_ids": ["comentario1", "comentario2"] } |
Al decidir cómo modelar tus datos en Couchbase, es esencial considerar cómo tu aplicación leerá y escribirá los datos. Si eliges incrustar comentarios dentro del documento del artículo, puedes conseguir operaciones de lectura más rápidas ya que todos los datos están contenidos en un único documento. Este enfoque es beneficioso cuando se necesita recuperar rápidamente un artículo junto con todos sus comentarios. Sin embargo, el inconveniente es que cualquier actualización del artículo o de sus comentarios requiere reescribir todo el documento. Esto puede resultar ineficaz, sobre todo si el documento es extenso o si las actualizaciones son frecuentes. Por lo tanto, incrustar comentarios es adecuado para escenarios en los que los comentarios rara vez se actualizan independientemente del artículo, y el rendimiento de lectura es crucial.
Por otro lado, hacer referencia a los comentarios por su ID permite actualizaciones más granulares. Cada comentario puede actualizarse independientemente del artículo, lo que hace más eficientes las operaciones de escritura. Sin embargo, este enfoque puede dar lugar a operaciones de lectura más lentas, ya que la recuperación de un artículo con todos sus comentarios requiere la obtención de varios documentos. Este patrón es ventajoso cuando los comentarios se actualizan con frecuencia o cuando el tamaño total del documento debe ser menor por razones de rendimiento.
Comprender estas ventajas y desventajas te ayudará a tomar decisiones informadas sobre cómo estructurar los datos en tu aplicación. Si consideras detenidamente los patrones de lectura y escritura de tu aplicación, podrás optimizar el rendimiento y garantizar una gestión eficaz de los datos.
El almacenamiento en caché de Rails reduce los problemas de rendimiento
Hay un método que puedes utilizar en tu aplicación Rails para mitigar la necesidad de siquiera deliberar sobre las posibles compensaciones entre utilizar un enfoque de documento incrustado o un enfoque de documento referenciado. Este método consiste en almacenar en caché y aprovechar ActiveSupport::Caché
. ¿Sabías que puedes hacerlo con Couchbase con una configuración adicional mínima?
El SDK Ruby de Couchbase incluye soporte para un almacén caché ActiveSupport específico para datos Couchbase. Esto le proporciona todos los beneficios de ActiveSupport para sus datos de documentos JSON. Echemos un vistazo rápido a cómo funcionaría esto.
Una vez que tengas instalado el SDK de Couchbase añadiendo gema couchbase
a su Gemfile y corriendo instalación del paquete
desde la línea de comandos, ya está listo para integrar el soporte de almacenamiento en caché en su aplicación Rails.
En primer lugar, defina el almacén Couchbase en su archivo config.rb:
1 2 3 4 5 6 |
config.cache_store = :tienda_base_coche, { cadena_de_conexión: # YOUR_COUCHBASE_CAPELLA_CONNECTION_STRING", nombre de usuario: TU_NOMBRE_DE_USUARIO_DE_LAS_CREDENCIALES_DE_ACCESO_A_COUCHBASE, contraseña: TUS_CREDENCIALES_DE_ACCESO_A_LA_BASE_DE_USUARIO_CONTRASEÑA", cubo: TU_BOLSA_CUBO_NOMBRE } |
A continuación, puede crear un método de ayuda en su aplicación para obtener cualquier dato y almacenarlo en la caché. Por ejemplo, supongamos que estás creando una plataforma de blogs. Una vez que se publica un artículo, a menudo permanece igual durante un largo período de tiempo, y por lo tanto es seguro mantenerlo en caché. Del mismo modo, si eliges incrustar comentarios en el documento JSON del artículo en Couchbase, puede que sólo necesites actualizar el documento y obtener una nueva copia en la caché cada vez que se añada un nuevo comentario, lo que sin duda será menos frecuente que obtener el documento para cada petición.
Su código puede parecerse al siguiente ejemplo. Creamos un método llamado#fetch_article_con_caching
que obtiene el artículo de Couchbase y analiza los resultados para obtener el contenido del artículo y el valor CAS. El valor CAS (Compare and Swap) representa el estado actual del documento, asegurando el control de concurrencia para cada operación de escritura. Ayuda a comprobar si el estado de los datos en la caché local coincide con el estado más reciente en la base de datos. Nuestro método utiliza el valor CAS para actualizar la caché de la aplicación o para devolver el artículo desde la caché, reduciendo los intercambios entre los datos incrustados en Couchbase y los modelos de datos relacionales tradicionales.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# Obtención de un artículo con almacenamiento en caché, comprobación de actualizaciones de los comentarios o del artículo def fetch_article_with_caching(artículo_id) clave_cache = "article_#{article_id}" # Obtener los metadatos del artículo (incluido el valor CAS) # El valor CAS es un testigo para el control de concurrencia, comprueba las actualizaciones de documentos resultado = Artículo.cubo.colección_por_defecto.consiga(artículo_id, Couchbase::Opciones::Visite(con_expiración: verdadero)) artículo = resultado.contenido cas = resultado.meta.cas # Obtener el artículo en caché junto con su valor CAS artículo_en_caché, cached_cas = Rieles.caché.leer(clave_cache) # Actualizar la caché si el artículo o sus comentarios han cambiado si artículo_en_caché.nil? || cached_cas != cas Rieles.caché.escriba a(clave_cache, [artículo, cas], caduca_en: 12 horas) si no artículo = en caché_artículo fin artículo fin # Ejemplo de uso artículo = fetch_article_with_caching("tu_articulo_id") |
No hay ActiveRecord... ¿o sí?
Podrías pensar que la transición a Couchbase significa decir adiós a la conocida librería ActiveRecord. Sin embargo, gracias a la nueva Couchbase Ruby ORMcon Couchbase, puedes seguir disfrutando de una experiencia similar a ActiveRecord cuando trabajes con Couchbase en tus aplicaciones Rails.
Couchbase Ruby ORM proporciona una capa ORM que imita la funcionalidad y sintaxis de ActiveRecord, facilitando la transición a los desarrolladores Rails. Esta librería tiende un puente entre el modelo relacional al que estás acostumbrado y el modelo de documentos utilizado por Couchbase. Ofrece una sintaxis con la que los desarrolladores Rails están familiarizados, reduciendo la curva de aprendizaje. Puedes definir modelos, establecer atributos e interactuar con la base de datos de forma similar a ActiveRecord.
Por ejemplo, tal vez necesite definir un Artículo y crear una nueva instancia de la misma. Usando el nuevo ORM, hacerlo con Couchbase es exactamente igual que hacerlo con ActiveRecord.
1 2 3 4 5 6 7 |
clase Artículo < CouchbaseOrm::Base atributo :título, tipo: Cadena atributo :contenido, tipo: Cadena atributo :comentarios, tipo: Matriz fin artículo = Artículo.crear(título: "Mi artículo", contenido: "Este es el contenido del artículo...") |
Incluso se pueden definir validaciones en el campo Artículo como lo haría con ActiveRecord.
1 2 3 4 5 6 7 8 9 10 |
clase Artículo < CouchbaseOrm::Base atributo :título, tipo: Cadena atributo :contenido, tipo: Cadena atributo :comentarios, tipo: Matriz fin ## Asegúrese de que cada nuevo artículo tenga un título valida :título, presencia: verdadero artículo = Artículo.crear(título: "Mi artículo", contenido: "Este es el contenido del artículo...") |
¿Qué ocurre con la creación de asociaciones entre distintos modelos? Tal vez quiera asegurarse de que un artículo puede obtener sus comentarios invocando un modelo #comentarios utilizando el método tiene_muchos macro. Esto también es posible.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
clase Artículo < CouchbaseOrm::Base # Definir la asociación y convertirla en una destrucción Dependencia # cuando se elimina un artículo tiene_muchos :comentarios, dependiente: destruir atributo :título, tipo: Cadena atributo :contenido, tipo: Cadena atributo :comentarios, tipo: Matriz fin valida :título, presencia: verdadero artículo = Artículo.crear(título: "Mi artículo", contenido: "Este es el contenido del artículo...") |
Consideraciones particulares
Cuando introduzcas Couchbase como tu base de datos en tu aplicación Rails, hay algunas cosas a tener en cuenta que al hacerlo con antelación harán que tu trabajo de desarrollo sea más fluido y eficiente. En primer lugar, como el ORM de Ruby es muy nuevo, aún no existe una librería de pruebas que puedas integrar en RSpec para crear tus mocks, stubs y definir matchers mientras construyes tus pruebas.
Esto significa que tendrá que definir sus propios mocks y otros elementos relacionados con las pruebas. Por ejemplo, puede crear un mock de un artículo y definir una expectativa en torno a él.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
RSpec.describa Artículo, tipo: :modelo do deje(:artículo) do Artículo.nuevo(id: artículo-id, título: Título de la prueba, descripción: Descripción de la prueba, cuerpo: Cuerpo de prueba, autor_id: autor.id) fin contexto al guardar un artículo do describa #save do it 'crea un nuevo registro de artículo en la base de datos' do permitir(Artículo).a reciba(:nuevo).y_devolución(artículo) permitir(artículo).a reciba(:guardar).y_devolución(verdadero) artículo.guardar espere(artículo.id).a eq(artículo-id) fin fin fin fin |
Otra característica importante de los datos de Couchbase que hay que recordar es la función de Metadatos en un documento Couchbase. Los metadatos incluyen varias piezas de información sobre el documento, como el ID del documento, el valor CAS, el tiempo de expiración, y más. Estos metadatos pueden ser útiles para gestionar e interactuar con tus datos.
Uno de los componentes clave de los metadatos es el ID del documento. El ID de documento es un identificador único para cada documento en Couchbase. Te permite recuperar, actualizar y borrar documentos basándote en este ID. A diferencia de las bases de datos relacionales, donde a menudo se utilizan claves primarias, Couchbase se basa en estos IDs de documento para identificar de forma única cada documento JSON.
Para acceder a los metadatos de cualquiera de tus documentos JSON, puedes crear una consulta personalizada utilizando el ORM de Ruby. En el ejemplo siguiente, el ID del documento se obtiene definiendo primero la consulta y luego un método para utilizarla. El método devuelve tanto el ID del documento como el resto de los datos del artículo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
clase Artículo < CouchbaseOrm::Base atributo :título, tipo: Cadena atributo :contenido, tipo: Cadena atributo :comentarios, tipo: Matriz # Consulta personalizada para obtener el ID de metadatos junto con los datos del artículo n1ql :by_id_con_meta, emitir_clave: [:id], consulta_fn: proc { |cubo, valores, opciones| grupo.consulta( " SELECT META(a).id AS meta_id, a.* FROM `#{bucket.name}` COMO a WHERE META(a).id = $1", Couchbase::Opciones::Consulta(parámetros_posicionales: valores) ) } fin # Obtener y mostrar el artículo con su ID de metadatos def fetch_article_with_meta_id(artículo_id) resultados = Artículo.by_id_con_meta(artículo_id) resultados.cada do |fila| meta_id = fila["meta_id"] datos_artículo = fila.rechace { |clave| clave == "meta_id" } pone "Meta ID: #{meta_id}" pone "Datos del artículo: #{article_data}" fin fin # Ejemplo de uso fetch_article_with_meta_id("tu_articulo_id") |
Si aún no estás familiarizado con Couchbase, puede que mires esa consulta y pienses que se parece mucho a SQL, ¡y estarías en lo cierto! Una de las grandes cosas de Couchbase es que introdujo un lenguaje de consulta - SQL - para documentos NoSQL que proporciona la misma experiencia para interactuar con ellos que la que se tendría con una tabla SQL. Trabajar con tus datos en Couchbase con SQL++ proporciona la misma funcionalidad y ergonomía con la que estás familiarizado en cualquier base de datos SQL. No hay necesidad de introducir ninguna sobrecarga cognitiva adicional a tu trabajo. ¡Eso es lo último que cualquiera de nosotros necesita!
1 |
SELECCIONE META(a).id AS meta_id, a.* DESDE `#{bucket.name}` AS a WHERE META(a).id = $1 |
Conclusión
La combinación de un ORM para proporcionar una experiencia similar a ActiveRecord para tus datos dinámicos NoSQL en Rails y un lenguaje de consulta similar a SQL para cubrir otros casos de uso ofrece una base de datos y un sistema de gestión de datos totalmente versátiles para tu aplicación. Si está interesado en explorar cómo es una implementación completa en funcionamiento, puede clonar y sumergirse en una aplicación Rails de ejemplo del mundo real que cubre todas las operaciones de creación, lectura, actualización y borrado utilizando el ORM de Ruby en GitHub.
Siempre que tu aplicación requiera datos que no se ajusten fácilmente a un esquema rígido o a una estructura estrictamente definida y estés buscando cómo acomodarlos, Couchbase con el nuevo ORM Ruby ofrece una solución convincente.