O Ruby on Rails costuma ser a estrutura escolhida para dar início a novos projetos. A velocidade de desenvolvimento e iteração é, em muitos aspectos, incomparável. Sendo assim, talvez você queira usar o Rails como a estrutura para seu aplicativo que requer muita flexibilidade nos dados e tem uma estrutura fluida. Talvez você esteja criando um aplicativo para a Internet das Coisas ou um sistema de gerenciamento de conteúdo que precise lidar com todos os tipos de dados. As soluções tradicionais de banco de dados para o Rails simplesmente não são suficientes. O que você deve fazer?
Neste guia, você descobrirá as considerações e as etapas para utilizar o Couchbase como banco de dados totalmente integrado ao seu aplicativo Rails. A decisão de criar com o Couchbase introduz não apenas mudanças na implementação técnica, mas também mudanças conceituais na maneira como você aborda seus dados. Vamos nos aprofundar nelas.
tl;dr Interessado apenas em ver o código? Confira um aplicativo de exemplo real totalmente desenvolvido que demonstra todas as ações CRUD com o Ruby on Rails e o Couchbase Ruby ORM em GitHub.
Modelo de documento vs. modelo relacional
No Rails, você está acostumado a trabalhar com um modelo relacional, normalmente usando o ActiveRecord. Os dados são organizados em tabelas com linhas e colunas, e os relacionamentos entre as entidades são definidos usando chaves estrangeiras. O Couchbase, por outro lado, usa um modelo de documento, em que os dados são armazenados em documentos JSON.
O modelo de documento permite mais flexibilidade nas estruturas de dados. Por exemplo, agora você pode armazenar dados aninhados diretamente no mesmo documento dos dados pai. Isso significa que, se você estiver criando uma plataforma de blog, os comentários sobre os artigos poderão ser anexados diretamente ao documento JSON de cada artigo, em vez de associar os comentários aos artigos pelo ID do comentário. A escolha de usar ou não esse recurso depende dos padrões de acesso e das considerações de desempenho que você deve considerar ao projetar seu aplicativo.
A diferença nos dados será parecida com os exemplos a seguir.
Comentários incorporados:
|
1 2 3 4 5 6 7 8 |
{ "título": "Meu artigo", "content" (conteúdo): "Este é o conteúdo do artigo...", "comentários": [ {"autor": "Usuário1", "texto": "Ótimo artigo!"}, {"autor": "Usuário2", "texto": "Obrigado pela informação."} ] } |
Por outro lado, o modelo tradicional com o qual a maioria dos desenvolvedores de Rails está familiarizada é parecido com este:
|
1 2 3 4 5 |
{ "título": "Meu artigo", "content" (conteúdo): "Este é o conteúdo do artigo...", "comment_ids": ["comment1", "comment2"] } |
Ao decidir como modelar seus dados no Couchbase, é essencial considerar como seu aplicativo lerá e gravará os dados. Se você optar por incorporar comentários no documento do artigo, poderá realizar operações de leitura mais rápidas, pois todos os dados estão contidos em um único documento. Essa abordagem é vantajosa quando você precisa recuperar rapidamente um artigo com todos os seus comentários. No entanto, a desvantagem é que qualquer atualização do artigo ou de seus comentários exige a reescrita de todo o documento. Isso pode ser ineficiente, especialmente se o documento for grande ou se as atualizações forem frequentes. Portanto, a incorporação de comentários é adequada para cenários em que os comentários raramente são atualizados independentemente do artigo, e o desempenho da leitura é crucial.
Por outro lado, a referência aos comentários por seus IDs permite atualizações mais granulares. Cada comentário pode ser atualizado independentemente do artigo, o que torna as operações de gravação mais eficientes. No entanto, essa abordagem pode resultar em operações de leitura mais lentas, pois a recuperação de um artigo com todos os seus comentários exige várias buscas de documentos. Esse padrão é vantajoso quando os comentários são atualizados com frequência ou quando o tamanho geral do documento precisa ser mantido menor por motivos de desempenho.
A compreensão dessas compensações ajuda a tomar decisões informadas sobre como estruturar os dados no aplicativo. Ao considerar cuidadosamente os padrões de leitura e gravação do seu aplicativo, você pode otimizar o desempenho e garantir um gerenciamento eficiente dos dados.
O armazenamento em cache do Rails ajuda a reduzir as compensações de desempenho
Há um método que você pode utilizar em seu aplicativo Rails para reduzir a necessidade de deliberar sobre as possíveis compensações entre usar uma abordagem de documento incorporado ou uma abordagem de documento referenciado. Essa abordagem é o armazenamento em cache e a utilização do ActiveSupport::Cache. Você sabia que pode fazer isso com o Couchbase com o mínimo de configuração adicional?
O SDK Ruby do Couchbase inclui suporte para um armazenamento em cache do ActiveSupport especificamente para dados do Couchbase. Isso lhe dá todos os benefícios do ActiveSupport para seus dados de documento JSON. Vamos dar uma olhada rápida em como isso funcionaria.
Depois que você tiver o SDK do Couchbase instalado, adicionando gem couchbase para sua Arquivo de gemas e em execução instalação do pacote na linha de comando, você está pronto para integrar o suporte a cache em seu aplicativo Rails.
Primeiro, defina o armazenamento do Couchbase em seu arquivo config.rb:
|
1 2 3 4 5 6 |
configuração.cache_store = :loja de base de sofá, { connection_string: # YOUR_COUCHBASE_CAPELLA_CONNECTION_STRING", nome de usuário: NOME DE USUÁRIO DE SUAS CREDENCIAIS DE ACESSO AO BANCO DE DADOS, senha: SUAS_CREDENCIAIS_DE_ACESSO_À_BASE_DE_TOQUES_SENHA", balde: SEU_COUCHBASE_BUCKET_NOME } |
Em seguida, você pode criar um método auxiliar em seu aplicativo para buscar qualquer dado e armazená-lo no cache. Por exemplo, digamos que você esteja criando uma plataforma de blog. Depois que um artigo é publicado, ele geralmente permanece o mesmo por um longo período de tempo e, portanto, é seguro mantê-lo no cache. Da mesma forma, se você optar por incorporar comentários no documento JSON do artigo no Couchbase, talvez seja necessário apenas atualizar o documento e buscar uma nova cópia no cache sempre que um novo comentário for adicionado, o que certamente será menos frequente do que buscar o documento para cada solicitação.
Seu código pode ser parecido com o exemplo a seguir. Criamos um método chamado#fetch_article_with_caching que busca o artigo no Couchbase e analisa os resultados para obter o conteúdo do artigo e o valor CAS. O valor CAS (Compare and Swap) representa o estado atual do documento, garantindo o controle de simultaneidade para cada operação de gravação. Ele ajuda a verificar se o estado dos dados no cache local corresponde ao estado mais recente no banco de dados. Nosso método usa o valor CAS para atualizar o cache do aplicativo ou retornar o artigo do cache, reduzindo as compensações entre os dados incorporados no Couchbase e os modelos de dados relacionais tradicionais.
|
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 |
# Buscar um artigo com cache, verificando se há atualizações nos comentários ou no artigo def fetch_article_with_caching(article_id) cache_key = "article_#{article_id}" # Obter os metadados do artigo (incluindo o valor CAS) # O valor CAS é um token para controle de simultaneidade, verifique se há atualizações de documentos resultado = Artigo.balde.default_collection.obter(article_id, Couchbase::Opções::Obter(com_expiração: verdadeiro)) artigo = resultado.conteúdo cas = resultado.meta.cas # Obter o artigo em cache junto com seu valor CAS artigo em cache, cache_cas = Trilhos.cache.ler(cache_key) # Atualize o cache se o artigo ou seus comentários tiverem sido alterados se artigo em cache.nulo? || cache_cas != cas Trilhos.cache.escrever(cache_key, [artigo, cas], expira_em: 12.horas) mais artigo = em cache_artigo final artigo final # Exemplo de uso artigo = fetch_article_with_caching("your_article_id") |
Não há ActiveRecord... ou há?
Você pode pensar que a transição para o Couchbase significa dizer adeus à conhecida biblioteca ActiveRecord. No entanto, graças à nova biblioteca Couchbase Ruby ORMSe o Couchbase for um aplicativo Rails, você ainda poderá desfrutar de uma experiência semelhante à do ActiveRecord ao trabalhar com o Couchbase em seus aplicativos Rails.
O Couchbase Ruby ORM fornece uma camada ORM que imita a funcionalidade e a sintaxe do ActiveRecord, tornando a transição mais suave para os desenvolvedores Rails. Essa biblioteca preenche a lacuna entre o modelo relacional com o qual você está acostumado e o modelo de documento usado pelo Couchbase. Ela oferece uma sintaxe com a qual os desenvolvedores do Rails estão familiarizados, reduzindo a curva de aprendizado. Você pode definir modelos, definir atributos e interagir com o banco de dados de forma semelhante ao ActiveRecord.
Por exemplo, talvez você precise definir um Artigo e criar uma nova instância dela. Usando o novo ORM, fazer isso com o Couchbase é exatamente igual a fazer isso com o ActiveRecord.
|
1 2 3 4 5 6 7 |
classe Artigo < CouchbaseOrm::Base atributo :título, tipo: Cordas atributo :conteúdo, tipo: Cordas atributo :comentários, tipo: Matriz final artigo = Artigo.criar(título: "Meu artigo", conteúdo: "Este é o conteúdo do artigo...") |
Você pode até mesmo definir validações no Artigo da mesma forma que você faria com o ActiveRecord.
|
1 2 3 4 5 6 7 8 9 10 |
classe Artigo < CouchbaseOrm::Base atributo :título, tipo: Cordas atributo :conteúdo, tipo: Cordas atributo :comentários, tipo: Matriz final ## Assegure-se de que cada novo artigo tenha um título valida :título, presença: verdadeiro artigo = Artigo.criar(título: "Meu artigo", conteúdo: "Este é o conteúdo do artigo...") |
E quanto à criação de associações entre modelos diferentes? Talvez você queira garantir que um artigo possa obter seus comentários invocando um modelo #comentários usando o método has_many macro. Isso também é possível.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
classe Artigo < CouchbaseOrm::Base # Defina a associação e transforme-a em uma destruição Dependência # quando um artigo é excluído has_many :comentários, dependente: destruir atributo :título, tipo: Cordas atributo :conteúdo, tipo: Cordas atributo :comentários, tipo: Matriz final valida :título, presença: verdadeiro artigo = Artigo.criar(título: "Meu artigo", conteúdo: "Este é o conteúdo do artigo...") |
Considerações exclusivas
Ao introduzir o Couchbase como banco de dados em seu aplicativo Rails, há algumas coisas a considerar que, ao fazer isso logo no início, tornarão seu trabalho de desenvolvimento mais suave e eficiente. Em primeiro lugar, como o Ruby ORM é muito novo, ainda não há uma biblioteca de testes que possa ser integrada ao RSpec para criar seus mocks, stubs e definir matchers à medida que você constrói seus testes.
Isso significa que você precisará definir suas próprias simulações e outros itens relacionados a testes. Por exemplo, você pode criar uma simulação de um artigo e definir uma expectativa em relação a ele.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
RSpec.descrever Artigo, tipo: :modelo fazer deixar(:artigo) fazer Artigo.novo(id: 'article-id', título: "Título do teste, descrição: 'Descrição do teste', corpo: 'Corpo de prova', author_id: autor.id) final contexto 'ao salvar um artigo' fazer descrever '#save' fazer ele 'cria um novo registro de artigo no banco de dados' fazer permitir(Artigo).para receber(:novo).e_retorno(artigo) permitir(artigo).para receber(:salvar).e_retorno(verdadeiro) artigo.salvar esperar(artigo.id).para eq('article-id') final final final final |
Outro recurso importante dos dados do Couchbase que deve ser lembrado é a função de Metadados em um documento do Couchbase. Os metadados incluem várias informações sobre o documento, como o ID do documento, o valor CAS, o tempo de expiração e muito mais. Esses metadados podem ser úteis para gerenciar e interagir com seus dados.
Um dos principais componentes dos metadados é o ID do documento. O ID do documento é um identificador exclusivo para cada documento no Couchbase. Ele permite que você recupere, atualize e exclua documentos com base nesse ID. Diferentemente dos bancos de dados relacionais, nos quais você costuma usar chaves primárias, o Couchbase depende desses IDs de documento para identificar exclusivamente cada documento JSON.
Para acessar os metadados de qualquer um dos seus documentos JSON, você pode criar uma consulta personalizada usando o Ruby ORM. No exemplo abaixo, o ID do documento é obtido definindo-se primeiro a consulta e, em seguida, um método para usá-la. O método retorna o ID do documento e o restante dos dados do artigo.
|
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 |
classe Artigo < CouchbaseOrm::Base atributo :título, tipo: Cordas atributo :conteúdo, tipo: Cordas atributo :comentários, tipo: Matriz # Consulta personalizada para buscar ID de metadados junto com os dados do artigo n1ql :by_id_with_meta, emit_key: [:id], query_fn: proc { |balde, valores, opções| agrupamento.consulta( "SELECT META(a).id AS meta_id, a.* FROM `#{bucket.name}` AS a WHERE META(a).id = $1", Couchbase::Opções::Consulta(parâmetros_posicionais: valores) ) } final # Obter e exibir o artigo com seu ID de metadados def fetch_article_with_meta_id(article_id) resultados = Artigo.by_id_with_meta(article_id) resultados.cada fazer |fila| meta_id = fila["meta_id"] dados_do_artigo = fila.rejeitar { |chave| chave == "meta_id" } coloca "Meta ID: #{meta_id}" coloca "Dados do artigo: #{article_data}" final final # Exemplo de uso fetch_article_with_meta_id("your_article_id") |
Se você ainda não estiver familiarizado com o Couchbase, talvez olhe para essa consulta e pense que ela se parece muito com SQL, e você estaria correto! Uma das grandes vantagens do Couchbase é que ele introduziu uma linguagem de consulta - o SQL. SQL++ - para documentos NoSQL que oferece a mesma experiência de interação com eles que se teria com uma tabela SQL. Trabalhar com os seus dados no Couchbase com o SQL++ oferece a mesma funcionalidade e ergonomia com as quais você está familiarizado em qualquer banco de dados SQL. Não há necessidade de introduzir nenhuma sobrecarga cognitiva adicional em seu trabalho. Essa é a última coisa que qualquer um de nós precisa!
|
1 |
SELECIONAR META(a).id AS meta_id, a.* DE `#{bucket.name}` AS a WHERE META(a).id = $1 |
Concluindo
A combinação de um ORM para fornecer uma experiência semelhante à do ActiveRecord para seus dados NoSQL dinâmicos no Rails e uma linguagem de consulta semelhante à do SQL para cobrir outros casos de uso oferece um sistema de gerenciamento de dados e banco de dados totalmente versátil para seu aplicativo. Se estiver interessado em explorar como é uma implementação funcional completa, você pode clonar e mergulhar em um aplicativo Rails de exemplo do mundo real que abrange todas as operações de criação, leitura, atualização e exclusão usando o Ruby ORM em GitHub.
Sempre que seu aplicativo exigir dados que não estejam facilmente em conformidade com um esquema rígido ou uma estrutura estritamente definida e você estiver procurando como acomodar isso, o Couchbase com o novo Ruby ORM oferece uma solução atraente.