Este curso é uma continuação, então é importante que você já tenha tido acesso aos conteúdos anteriores. Dito isso, abriremos o projeto em que estávamos trabalhando. Caso você já conheça o conteúdo do curso anterior e queria começar a partir daqui, basta realizar o download do projeto no GitHub, o link se encontra disponível no menu de atividades.
Uma vez que o projeto estiver aberto, clicaremos sobre "project.clj > Run 'REPL for...'". Feito isso, queremos executar também o Datomic. Com o terminal aberto no diretório do Datmic-pro, executaremos o comando bin/transactor e o arquivo de configurações do transactor.
Quando o processo estiver finalizado, teremos tanto o Datomic rodando quanto REPL.
Temos os arquivios das aulas antigas, nós manteremos aqueles que criam o banco com o esquema antigo e adiciona alguns produtos. Na aula6.clj, criamos a conexão com o banco, adicionamos alguns produtos e buscamos por eles logo em seguida.
(def conn (db/abre-conexao))
(db/cria-schema conn)
(let [computador (model/novo-produto "Computador Novo", "/computador-novo", 2500.10M)
celular (model/novo-produto "Celular Caro", "/celular", 888888.10M)
calculadora {:produto/nome "Calculadora com 4 operações"}
celular-barato (model/novo-produto "Celular Barato", "/celular-barato", 0.1M)]
(pprint @(d/transact conn [computador, celular, calculadora, celular-barato])))
Reutilizaremos esse código em aula1.clj, além de mantermos o namespace. Também adicionaremos o código que realiza uma busca que traz todos os produtos ((pprint (db/todos-os-produtos (d/db conn)))), além disso, adicionaremos também o código de apagar o banco, caso seja do nosso interesse (;(db/apaga-baco)). O arquivo ficará com o seguinte conteúdo:
(ns ecommerce.aula1
(:use clojure.pprint)
(:require [datomic.api :as d]
[ecommerce.db :as db]
[ecommerce.model :as model]))
(def conn (db/abre-conexao))
(db/cria-schema conn)
(let [computador (model/novo-produto "Computador Novo", "/computador-novo", 2500.10M)
celular (model/novo-produto "Celular Caro", "/celular", 888888.10M)
calculadora {:produto/nome "Calculadora com 4 operações"}
celular-barato (model/novo-produto "Celular Barato", "/celular-barato", 0.1M)]
(pprint @(d/transact conn [computador, celular, calculadora, celular-barato])))
(pprint (db/todos-os-produtos (d/db conn)))
;(db/apaga-baco)
Deletaremos todos os arquivos restantes que não usuaremos.
Estamos o usando o banco ecommerce, mas não sabemos o que há dentro dele, como podemos fazer essa exploração? No Datomic existe a ferramenta Datomic console, em que podemos fazer essa exploração pela linha de comando. Na documentação da ferramenta, encontraremos um exemplo de utilização:
bin/console -p 8080 dev datomic:dev://localhost:4343/
Abriremos uma nova aba na linha de comando, acesaremos o diretório do Datmoc e executaremos o comando com as devidas alterações. Terminado esse processo, poderemos acessar o logalhost, e então copiaremos esse endereço no navegador.
Acessaremos, assim, o console ou explorador visual do Datomic.
Na página, teremos uma série de informações. Na opção "DB" teremos o banco "ecommerce", que utilizamos no curso anterior. Nesta opção será exibido todos os bancos que nós temos. Quando selecionamos o banco de dados, também teremos acesso aos identificadores básicos que havíamos criado,além dos padrão do Datomic.
![banco de dados - console do Datonic. Opção "DB" selecionada como "ecommerce". Na área "Schema" são visíveis os indetificadores básicos]()
Temos inclusive os produtos disponívies nesse esquema. É importante frisar que esse esquema, apesar de ser inserido em um determinado momento, ele é atemporal, funciona para todos os momentos do banco.
Nosso objetivo é fazer uma query. Selecionaremos a aba "query", e poderemos fazer uma serie de configurações visuais.
![query - area de configuracao da query que contém campos a seeremo preenchidos. Dentro desta área, encontraremos a subdivisão "Where", em que teremos o campo ":db/doc"]()
Ao mantermos a opção ":db/doc", poderemos trazer, por exemplo, produto/nome. Então executaremos essa query, e o valor de ":db/doc" será "?doc", o terceiro parâmetro da query. Na opção "Find" encontraremos tanto a entidade quanto no doc, portanto teremos "?e?doc".
Teremos várias entidades, inclusive a 72, que é o nome de um produto. A query está funcional, mas poderia ter sido feita de todos os produtos, por exemplo. Ao invés de ":db/doc", escreveremos ":produto/nome". No valor escreveremos "?nome". No campo "Find" escreveremos "?e ?nome".
Como resultado teremos todos os nossos quatro produtos: celular barato, celular caro computador novo e calculadora com 4 operações. Podemos também buscar o preço de cada um dos produtos incluindo "produto/preco", valor "?preco" e no "Find" escreveremos "?e?nome?preco". Agora teremos os nomes e preços do produto, lembrando que calculadora de 4 dígitos não possuía um preço estipulado, portanto não surgiu na tela.
O console é útil para executarmos querys e explorarmos algumas configurações de acordo com a necessidade do projeto.
Ao retornarmos para o nosso código, podemos apagar o banco de dados e adicioná-lo novamente, completamente limpo. Feito isso, abriremos a conexão de novo com o banco e criamos novamente o esquema, também limpo. Ao executarmos novamente a query e buscarmos por nome do produto, não encontraremos nada.
Com o banco limpo, adicionaremos os quatro produtos ao executarmos nosso código. Eles estarão novamente visíveis no console.
E se ao invés de buscarmos todos os produtos, nosso interesse seja em apenas um específico, como "celular barato"? Nós tempos o identificador desse produto, e então queremos trazer os dados desse produto baseado nessa informação. Nós queremos simplesmente fazer um pull na numeração do id, mas via console isso ficará complicado, pois não estamos interessados nos outros campos da query.
É possível realizar só o pull. Em nosso código, escreveremos a conexão com o banco mais o id do produto:
(pprint (db/um-produto (d/db conn) 17592186045421))
No banco, criaremos a função um-produto que receberá o banco e produto-id.
(defn um-produto [db produto-id])
(d/pull db '[*] produto-id))
Neste ponto precisamos ficar atentos. No "Find" o padrão das queries deve ser escapado, o mesmo ocorre aqui.
Feito isso, recarregaremos o arquivo, e ao executarmos o código veremos que o produto foi capturado com sucesso.
Existem outras maneiras que conseguir coletar um único produto, como coletar o primeiro deles:
(def produtos (db/todos-os-produtos (d/db conn)))
(def primeiro-produto-id (-> produtos
first
first
:db/id)
))
(println "O id do primeiro produto é" primeiro-produto-id)
(print (db/um-produto (d/db conn) primeiro-produto-id))
É razoavelmente comum que tenhamos a busca só pelo id das entidades e algumas vezes já temos o pull, que transforma os dados de acordo com o modelo estabelecido.