Olá, pessoal, meu nome é Guilherme Silveira e serei o instrutor no curso de Introdução ao Datomic: Um banco cronológico
Nesse curso vamos estudar um banco de dados diferente chamado Datomic. O Datomic não armazena os dados da maneira tradicional que comumente aprendemos, os bancos de dados de entidade relacional que formam grandes tabelas com vários campos e várias linhas. Essas não são as únicas maneiras de fazer banco de dados. Existem diversas outras como chave-valor, documento, grafo, entre outras.
O Datomic tem uma abordagem diferente. Há dois grandes pontos que vamos ver a partir deste primeiro curso. Um delas é que tudo que se faz neste banco se acumula, ou seja, fica armazenado num histórico. Ele não vai apagar o passado, então quando apagarmos um produto do sistema, ele não apaga de verdade. Essas informações ficam escondidas, mas ninguém acessa, ninguém percebe que está ali, todo mundo vê o banco na sua última versão.
As informações ficam armazenadas para haver a possibilidade de voltar no tempo e fazer uma auditoria se quisermos, e verificar por quem, quando e por que um dado foi apagado. Tudo isso estará armazenado no banco.
Conseguimos até fazer simulações do futuro, de como estaria o banco se fizéssemos certas transações devido ao armazenamento desse log.
Também por não trabalhar com várias tabelas, temos uma grande mudança na maneira de pensar em que conseguimos aplicar ferramentas genéricas a uma única tabela.
Poderemos criar comportamentos para diversos tipos de entidades de uma vez só de uma maneira mais simples com o Datomic Cloud pois isso será natural para ele.
Passaremos por seis aulas em que vamos acessar o banco, criar dados, esquemas, incluir dados, entender como eles estarão armazenados, fazer queries cada vez mais complexas, isolar nosso código das queries e fazer diversos acessos a medida que desenvolvemos essas queries de maneira mais complexa, conforme entendemos como funciona o Datomic.
Vamos começar nossos estudos.
Nosso primeiro passo, então, será baixar e instalar o Datomic. Para isso, vamos em datomic.com/get-datomic.html. Baixaremos a versão Starter, que é equivalente a versão Pro, mas gratuita.
Existem duas verões gratuitas do Datomic, a Starter e a Free, que tem outros tipos de restrições. Como a Starter é equivalente a Pro, que talvez você queira adquirir quando for utilizar o Datomic em maior escala, faremos o download dessa.
Quando clicarmos em Download Starter
teremos que criar a conta. Após criar a conta, será enviada uma licença no e-mail válida por um período determinado por um ano atualmente. Quando ela expirar, basta pedirmos outra.
Voltando ao site, na barra superior, vamos em Downloads
, que é a segunda opção. Baixaremos a versão mais recente, a "0.9.5951", e faremos a instalação em algum diretório. Como é um arquivo zipado, precisaremos descompactar.
Tal qual qualquer servidor de banco de dados, ele é um programa que você roda, então na versão padrão vamos simplesmente rodá-lo. Descompactamos e movemos para o diretório.
Pelo terminal vamos entrar nesse diretório. O que precisamos fazer agora é colocar nossa licença. Para isso, primeiro precisamos pegar o texto que nos enviaram por e-mail. Em seguida, copiamos o texto e colamos em um arquivo que o Datomic vai ler.
Em Local Dev Setup encontraremos o caminho para o processo de instalação. Após baixar e descompactar o arquivo, o que já fizemos, a documentação indica que devemos inserir a licença em um arquivo do tipo dev-transactor-templates-properties
. Então o Datomic vai rodar um primeiro program, capaz de escrever dados no banco, que precisa da nossa licença.
Vamos entrar em config
> samples
> dev-transactor-template.properties
. Esse arquivo é que vamos editar, então abriremos o sublime
no editor de texto - pode ser qualquer um - e vamos abrir este arquivo. Nele aparecerá um espaço com license-key=
onde colaremos a licença, salvaremos e na sequência vamos fechar.
Vamos copiar esse arquivo e jogar no diretório do nosso Datomic, fora de samples
e dentro de config
.
Será avisado para colocarmos bin/transactor
e o caminho do nosso arquivo, ou seja, config/dev-transactor-template.properties
> =Enter
. Assim que a transação terminar, será alertado que o servidor inicializou como datomic:dev://localhost:4334/ o nome do banco <DB-NAME>
. Vamos guardar os dados em data
.
System started datomic:dev://localhost:4334/<DB-NAME>, storing data in: data
Então, ele pretende utilizar o diretório data
para guardar os dados do banco que criarmos, a assim rodaremos o Datomic.
Nesse momento queremos nos conectar com ele, para isso abriremos o IntelliJ e criaremos um projeto novo. Vamos escolher um projeto de Clojure utilizando o Leiningen. Em seguida, escolheremos um diretório do projeto de acordo com o que for melhor para cada um e nomearemos o projeto como "ecommerce", já que trabalharemos com um sistema de ecommerce.
Tendo criado o projeto, teremos que instalar a biblioteca. Criaremos um banco usando a datomic api
, que precisaremos antes baixar. Na página do Dev Setup vamos em Overview e selecionaremos o modo *Peer Library.
Para instalar esse modo, teremos que utilizar a dependência [com.datomic/datomic-EDITION"VERSION"]
que copíaremos e colaremos em project.clj
. A versão que estamos utilizando, a mais atual, é a 0.9.5951
, entretanto será apresentado um erro se for colado esse número
Podemos ir em mvcentral e buscar o artefato do Datomic Pro. Colocamos a versão, vamos no Leiningen e atualizaremos. Mesmo assim não conseguiremos baixar a dependência porque a versão do Datomic Pro peer não fica em um repositório aberto, fica em uma espaço controlado pelo Datomic. Como o download depende da licença, é possível para a empresa controlar quem baixou a biblioteca.
Por isso, voltaremos para nossa conta logada e em My Account descemos a página até or via leiningen
onde é explicado como baixamos a bibliotecas via Leiningen. Em nosso arquivo ~/lein/credentials.clj.gpg
teremos que colocar alguma informação. Para isso, vamos no terminal, abrimos uma nova aba, vamos no diretório e criamos um novo diretório chamado .lein
.
No arquivo credentials.clj.gpg
adicionaremos o via
copiando as linhas de código encontradas na página.
{#'my\.datomic\.com" {:username "guilherme.silveira@caelum.com.br"
password "781e9538-97e0-43fd-ba36-840c06080743'}}
Salvamos o arquivo de credenciais. É avisado também para alterar o project.clj
, então também copiamos e colamos as duas linhas de código.
: repositores {"my.datomic.com" {:url "https://my.datomic.com/repo"
:cred :gpg}}
:dependencies [[com.datomic/datomic-pro $VERSION]]
Em projects
vamos adicionar uma nova opção. Agora colocaremos a versão 0.9.5951
, salvaremos e tentaremos atualizar.
Vamos fechar o IntelliJ e abrir de novo para garantir que o lein
começou do zero. Assim que terminar de abrir, reciclaremos novamente.
Há diversas maneiras de baixar esse jar
, a página inicial da nossa conta descreve algumas formas para isso. Quando já tivermos baixado um zip
, encontraremos um datomic-pro-0.9.5951.jar
.
Vamos nos conectar com esse banco de dados a partir do nosso código, então precisaremos da biblioteca, dojar
do Datomic e da dependência. Também vamos baixá-la no site.
Na documentação veremos que peer library e "Installing from Datomic distribution" bastará usarmos o comando bin/maven-intall
no Linux ou no Mac ou, ainda a opção para Windows. Entrando nesse diretório, executaremos esse bin
. Vamos baixar o Maven aqui. Escolhemos a primeira opção. Copiaremos a pasta apache-maven-3.6.2
para nosso diretorio apps
.
Não acharemos o mvn
, porque ele tem que estar em nosso paf
. Então se voltarmos no diretório e entrarmos no apache maven
teremos o diretório do Maven. Podemos dar um pwd
para vê-lo e então exportar a nossa path
com variável de path
mas o diretoria/bin
.
export PATH=$PATH:/Users/aluralaranja/Documents/Guilherme/datomic1-introducao/apps/apache-maven-3.6.2/bin.
Serão procurados os programas nos locais em que já eram buscados anteriormente e no diretório bin
desse projeto. Se rodar um mvn
, vai carregar. Vamos entrar de novo no diretório do Datomic e rodar aquele bin/maeve-intall
. Agora o Datomic será instalado
Logo são dois Datomics: um é o servidor do banco de dados e outro é a biblioteca para se conectar com o servidor.
Como já instalamos, vamos em nossas dependências. Além do Clojure, queremos instalar a dependência com o Datomic Pro e a versão 0.9.5961
.
[[org.clojure/clojure "1.10.0"]
[com.datomic/datomic-pro "0.9.6961"]]
Salvamos esse arquivo e vamos recarregá-lo, conforme a recomendação.
O sistema procurará o jar
do Datomic Pro para que possamos conectar e fazer um primeiro teste.
Vamos rodar nosso project.clj
, que o RELP
padrão que vai carregar. Vamos rodar esse código que é um código simples que vai requerer a biblioteca deles e vai manifestar querer no localhost na porta 4334
em um banco de dados chamado hello
.
Em seguida chamamos um d/create-database
para criar esse banco de dados. Quando rodamos o nosso banco de dados ele estava falando que é na porta 4334
, o que vamos comparar para ter certeza que está certo.
(require '[datomic.api :as d])
(def db-url "datomic:dev://localhost:4334/hello")
(d/create-database db-url)
Será devolvido true
, temos um banco de dados criado. Se tentarmos de novo criar esse banco, devolve false
porque ele já existe.
Então esse é o processo de instalação tanto do Datomic, quanto da biblioteca que ele é cliente, mas vamos chamar de peer nessa situação. No próximo vídeo, faremos a criação do banco de dados.
Temos nosso servidor e nossa biblioteca. Agora já conseguimos escrever códigos.
Dentro da CRC Commerce, temos o arquivo core.clj
. Vamos apagá-lo, pois não utilizaremos o código que ele tem por padrão. Criaremos um novo arquivo Clojure Namescape para gerar um novo Namespace que será o core
. É obrigatório que ele exista porque o Leiningen. vai carregá-lo para nós.
Vimos na documentação como fazíamos para criar um banco de dados. Demos um require
, um def
e um create
. Copiaremos esse código que foi o executado.
Será necessário um cuidado: nós executamos esse códigos aqui no RELP, que requer o scape
, já que estamos evocando a função require
. Nós o usamos como um chave dentro do Namespace, então não temos aquele scape
.
(ns ecommerce.core
(:require [datomic.api :as d]))
Então, em seguida definiremos URI e criaremos o banco.
(def db-uri "datomic:dev://localhost:4334/hello")
(d/create-database db-uri)
Criado o banco, nos conectaremos a ele. Para isso, vamos chamar um d/conect
. Isso devolverá uma conexão que chamaremos de conn
(def conn (d/connect db-uri))
Se quisermos, podemos apagar esse banco com d/delete
depois de fazer a conexão.
(d/delete-database db-ui)
Para ver isso tudo funcionando, podemos usar o pprint
(ns ecommerce.core
(:use clojure.pprint)
(:require [datomic.api :as d]))
(def db-uri "datomic:dev://localhost:4334/hello")
(pprint (d/create-database db-uri))
(def conn (d/connect db-uri))
(pprint conn)
(pprint (d/delete-database db-uri))
Salvamos e já podemos rodar. Tudo estará no core
então será carregado assim que rodarmos. Como o banco já existe, ele dará false
para o create
, mas os demais funcionarão da maneira esperada.
Isolaremos esse tipo de tarefa ligada ao banco em um arquivo. Se o projeto for muito pequeno, talvez terá um New Namespace que possamos chamar de db
. Se quisermos um projeto maior, podemos criar mais arquivos dentro de, apenas um já será o suficiente.
Vamos pegar esse código de infraestrutura do banco e colocá-lo dentro do Namespace. Claro, vamos precisar do require
e do use
. Deixaremos o db-uri
no mesmo local. Agora o banco será de ecommerce
não mais hello
.
Definiremos uma função agora, e poderíamos determinar que ela abre uma conexão. depois que conectamos e fizemos seja o que for,
Poderíamos criar uma função abre-conexao
que não receberá nada e vai criar o banco e conectar. Não é preciso definir a variável do connect
porque só queremos retornar a conexão, então criamos o banco e conectamos. Então abrimos a conexão. Se o banco já existe, não faça nada, apenas conecte.
Além disso, vamos criar uma outra função apaga-banco
que também não recebe nada e faz um delete
.
(ns ecommerce.db
(:use clojure.pprint)
(:require [datomic.api :as d]))
(def db-uri "datomic:dev://localhost:4334/ecommerce")
(defn abre-conexao []
(d/create-database db-uri)
(d/connect db-uri))
(defn apaga-banco []
(d/delete-database db-uri))
Podemos pensar que o create-database
deveria estar em outro lugar, mas isso poderá ser definido de acordo com o que parecer melhor.
Voltando ao core
, precisaremos comportar o db
com ecommerce.db :as db
. Em seguida, chamamos um db/abre-conexao
. Isso deveria definir a conn
então vamos dar um pprint
nela.
(ns ecommerce.core
(:use clojure.pprint)
(:require [datomic.api :as d]
[eecommerce.db :as db]))
(def conn (db/abre-conexao))
(pprint conn)
Então vamos recarregar esse arquivo. Ele recarrega e imprime a Connection.
Agora que já conseguimos estruturar alguns itens de banco, o que precisaremos fazer será colocar dados dentro do banco. Como vamos trabalhar em um sistema de ecommerce
, é natural que queiramos simular um exemplo que armazena vários produtos.
O nome de um produto será um String, também uma RI que vamos chamar de slug
, que será um caminho para acessá-lo. Enquanto o nome de um produto pode ser Computador Novo
o slug
- que também será uma String - pode ser /computador_novo
.
Além disso, teremos o preço, um ponto flutuante, e pode ser 3500.10
, por exemplo. Essa, então, é nossa estrutura, o esquema que temos para nossos produtos.
; Produtos
; nome String 1 ==> Computador Novo
; slug String 1 ==> /computador_novo
; preço ponto flutuante 1 ==> 3500.10
Essa seria a ideia de um banco de dados fracional. Em um banco de dados relacional baseado em SQL é muito comum que criemos uma tabela de produtos com três colunas, nome, slug e preço e, possivelmente uma coluna identificadora, de ID. Vamos jogar isso dentro do ecommerce.db
porque são estruturas do banco de dados.
Se no SQL temos um creat-table
para criar essa tabela, como fazemos para criar isso no Datomic? No Datomic, não vamos pensar em várias tabelas, mas em uma grande tabela. Nela, por exemplo, para o produto cujo ID é 15
, o nome
será Computador Novo
, o slug
será /computador_novo
, e preco
de 31500.10
.
Assim estaremos atribuindo ao ID da entidade id_entidade
, e teremos o atributo e o valor.
; id_entidade atributo valor
; 15 :nome Computador Novo
; 15 :slug /computador_novo
; 15 :preço 3500.10
Para outro produto, por exemplo, 17
fazemos o mesmo procedimento. O nome
pode ser Telefone Caro
, slug
/telefone
e preco
8888.88
.
; 17 :nome Telefone Caro
; 17 :slug /telefone
; 17 :preço 8888.88
Teremos uma única tabela, mas com as linhas ligadas através do ID da entidade. Aprenderemos outras informações a respeito delas com o passar do tempo.
Alcançaremos uma forma de descrever essa estrutura para nosso banco. Para isso definiremos uma função, por exemplo, model/novo-produto
de nome Computador Novo
cujo slug é /computador_ novo
e o preço é 2500.10
.
(model/novo-produto "Computador Novo", "/computador_novo", 2500.10)
Então essa será uma função de modelo que vamos ter de criar. A criação será simples e a adicionarmos ao require
(:require [datomic.api :as d]
[ecommerce.db :as db]
[ecommerce.model :as model])
Dentro desse modelo, selecionamos Ctrl + N
para criar o Namespace novo, de nome model
. Com a função de def novo-produto
que receberá o nome do produto, o slug e o preço e devolverá o mapa.
(defn novo-produto [nome slug preco]
{:nome nome
: slug slug
: preco preco})
Voltando ao core
, poderíamos apenas rodar isso e imprimir o resultado.
(pprint (model/novo-produto "Computador Novo", "/computador_novo", 2500.10))
Perfeito, imprime o computador. Mas o que queremos é colocar esse mapa dentro do banco. Para isso, chamamos a função d/transact
, ou seja, transacionamos, colocamos dentro disso várias informações. Lembre-se, em um banco de dados tradicional, a transação pode ser um ou vários insert
em uma tabela. Aqui também a transação será de vários itens.
Então no d/transact
vamos dar a conexão conn
e o que queremos colocar lá dentro, que é o novo-produto
. Então na verdade em vez de darmos print
vamos dar um let
e chamaremos de computador
. Na sequência tentaremos transacioná-lo.
(let [computador (model/novo-produto "Computador Novo", "/computador_novo", 2500.10)]
(d/transact conn computador))
Só um cuidado, o computador
é um mapa, o transact
recebe a conexão e uma sequência - nesse caso, um vetor - com um único item que queremos transacionar.
(let [computador (model/novo-produto "Computador Novo", "/computador_novo", 2500.10)]
(d/transact conn [computador])
Então podemos recarregar esse arquivo, ele imprime a conexão para nós e aparecerá como Loaded
. Se rodarmos esse d/transact
de novo, ele funcionará.
Vamos então tentar carregar o arquivo e vamos tentar executar esse código com Shift + L
. Carregou, mas ele não executou o d/transact
? Não tem problema, com o cursor selecionaremos d/transact
e pressionaremos Shift + P
para forçar a execução. Apesar de ter sido executado, aparecerá um erro. Vamos analisá-lo.
Não será mais necessário imprimir, então podemos apagar
pprint conn
.
O erro será :db.error/not-an-entity Unable to resolve entity: :nome
. Será apontado que nome
não é um entidade. novo-produto
será um produto que tem nome
slug
e preço
, três chaves. Essas chaves serão as indicadoras dos atributos, então de algum modo será preciso indicar isso a eles. Assim como no SQL indicamos "crie uma tabela que tem três campos", aqui, teremos que falar o que vamos chamar de atributos.
Também chamaremos esses atributos e vamos criá-los. indicaremos que esse atributo nome
é uma String e único - no sentido de só ter um dele. Um produto tem uma slug
e é uma String. O preco
tem ponto flutuante e é único também. Nos faltará indicar essas características, por isso ele não achou nome
.
O nome
do produto pode ser um, mas o nome
do usuário poderá ter outra regra e assim por diante. Por essa razão, o mais adequado será usarmos :produto/nome
, usar keywords que são identificadores com o namespace, já que se tiver um outro
nome` com outras características não haverá conflito.
; id_entidade atributo valor
; 15 :produto/nome Computador Novo
; 15 :produto/slug /computador_novo
; 15 :produto/preço 3500.10
; 17 :produto/nome Telefone Caro
; 17 :produto/slug /telefone
; 17 :produto/preço 8888.88
Então o que queremos fazer agora é definir esse esquema. Um schema
é um lista de definições. Queremos definir primeiro que temos um identificador ident
que se chama produto/nome
e ele terá um tipo de valor (valueType
) db.type/string
. Foi dito que um produto tem um nome
, então a cardinality
é um db.cardinality/one
.
Podemos colocar também a documentação, nesse caso pode ser "O nome de um produto"
, por exemplo.
(def schema [{:db/ident :produto/nome
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "O nome de um produto"}])
Do mesmo jeito que fizemos esse mapa, podemos colocar outros, outro db/ident
que pode ser o produto/slug
. Ele tem tipo de valor de string
, cardinalidade one
e doc
que pode ser "Caminho para acessar esse produto via http"
.
Por fim, vamos ter também o preço. ident
é produto/preco
. E o valuType?
Vamos na documentação ver os tipo, encontramos float
e double
mas eles tem o problema do arredondamento, ou seja, não tem precisão. Vamos escolher então o BigDecimal, assim :db.type/bigdec
. Cardinalidade também será one
e doc
"Preço de um produto"
.
{:db/ident :produto/slug
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "O caminho para acessar esse produto via http"}
{db/ident :produto/preco
:db/valueType :db.type/bigdec
db/cardinality :db.cardinality/one
db/doc "O preco de um produto com precisão monetária"}
Nosso esquema serão dados sequências de mapas, como tudo que trabalhamos em clojure
. Agora queremos transacionar esse esquema. Assim como o nosso produto é um dado, o esquema e estrutura são mapas e utilizaremos esses flashmaps.
Voltando a ecommerce.core
, antes de tentar transacionar o computador
vamos transacionar na conexão conn
o db/schema
. Mas antes precisamos recarregar as mudanças que fizemos em ecommerce.db
.
(db/transact conn db/schema)
Executamos e teremos um resultado bem grande. Os resultados do Datomic são, em geral, enormes. Conseguimos interpretar o que acontecerá transaction-data
com o passar do tempo. No instante 2019-09-18T14:34:22.896-00:00"
terá ocorrido a transação 13194139534312
. Essa transação aparecerá várias vezes porque só fizemos uma. O quarto valor do banco é o ID da transação ID_TX
.
clojure
#datom [72 10 :produto/nome 13194139534312 true]
#datom [72 40 23 13194139534312 true]
#datom [72 41 35 13194139534312 true]
#datom [72 62 "O nome de um produto" 13194139534312 true]
#datom [73 10 :produto/slug 13194139534312 true]
#datom [73 40 23 13194139534312 true]
#datom [73 41 35 13194139534312 true]
#datom [73 62 "O caminho para acessar esse produto via http 13194139534312 true]
Aqui vemos que para a entidade 72
temos o atributo 62
, o valor "O nome de um produto"
. Para a entidade 72
o 41 tem valor 35, para a entidade 72, 10 tem o valor :produto/nome
. Provavelmente, db.type/string:
é o 23, o cardinality/one
é o 35
, o valueType
é o 40
E pode ver que quando chegamos no slug 73
, são esses números que ele repete. Assim como vamos supor que 72
é o produto/nome
, 73
produto/slug
e 74
o produto/preco
.
Então em vez dele ficar sempre referenciando, usa um atalho e tem um identificador para os identificadores que utilizamos.
Todos esses b@datoms
serão colocados no banco, porque true
que dizer que foram incluídos, false
é de retirada. O quinto valor se referirá a operação realizada, de colocada ou de retirada.
Serão devolvidos alguns identificadores para os nossos produtos. Então se quiséssemos, no retorno de uma transação, conseguimos pegar os IDs que foram gerados e saber exatamente o que foi colocado dentro do banco, o resultado do d/transact
.
Não queremos deixar isso ser feito assim toda vez, porque se executarmos novamente o Datomic perceberá que esses datom
s já estarão lá e não deverão ser adicionados novamente, definindo o produto/nome
, produto/slug
e o produto/preco
. Então podemos executar o transact
do mesmo esquema diversas vezes, desde que não tenha alterações.
Extrairemos uma função db/cria-schema
que recebe a conn
para isolar isso dentro do nossos ecommerce.db
.
(defn cria-schema [conn]
(d/transact conn schema))
E agora se tentarmos adicionar a pessoa no banco, será que vai funcionar? Repare, agora já existe o produto/nome
, produto/slug
e produto/preco
.
(def conn (db/abre-conexao))
(db/cria-schema conn)
(let [computador (model/novo-produto "Computador Novo", "/computador_novo", 2500.10)]
(d/transact conn [computador]))
Dará erro e o programa dirá que a entidade nome
não existe. Isso ocorreu porque em ecommerce.model
o novo-produto
está usando nome
, slug
e preco
, quando deveria estar usando produto/nome
, produto/slug
e produto/preco
.
(defn novo-produto [nome slug preco]
{:produto/nome nome
:produto/slug slug
:produto/preco preco})
Assim conseguimos fazer direto a transferência do modelo pro banco.
Teremos problemas porque usamos 2500.10
com o valueType
bigDec
, mas esse é um valor double
. Adicionando M
transformamos ele em um valor bigDecimal
.
(def conn (db/abre-conexao))
(db/cria-schema conn)
(let [computador (model/novo-produto "Computador Novo", "/computador_novo", 2500.10M)]
(d/transact conn [computador]))
Agora dará certo. Será colocado no banco um "Computador Novo"
cujo slug é /computador_novo
e o valor 2500.10M
. De fato, 72
era produto/nome
73
produto/slug
e 74
produto/preco
. Mas não precisaremos decorar esses IDs, pois essa transformação ocorrerá sozinha. O Datomic ainda anota quando isso ocorreu.
#inst"2019-09-18t14:40:22.669-00:00"
Dessa criamos um esquema e transacionamos dados que estarão dentro do Datomic.
Nos próximos vídeos continuaremos editando dados no banco.
O curso Datomic: um banco cronológico possui 144 minutos de vídeos, em um total de 35 atividades. Gostou? Conheça nossos outros cursos de NoSQL em Data Science, ou leia nossos artigos de Data Science.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.