Introdução ao MongoDB
Por que usar o banco de dados NoSQL?
• Para uma aplicação que armazene os ganhadores do prêmio Nobel, da forma tradicional, teríamos:
• Desvantagens
1. montamos toda estrutura baseada nas limitações de um banco de dados (no mundo real não existe representação da tabela auxiliar premio_autor);
2. não pensamos no que a aplicação vai fazer, pensamos apenas em arrumar os dados;
Por que usar o banco de dados NoSQL?
• No MongoDB, organizamos os dados em função da aplicação.• Não temos tabelas, temos conjuntos de dados chamados collections,
que, ao contrário de tabelas, não têm constraints (chave primária, chave estrangeira) e nem transações, além de não ter as limitações de uma tabela relacional. Dentro de uma coluna, você pode ter um array, uma lista de valores, algo impossível em uma tabela convencional.
• As informações são organizadas dessa maneira:
Resumindo: da maneira convencional, a sua aplicação obedece às regras do seu banco de dados; no MongoDB é o contrário: é a sua aplicação que
JSON
• O estilo de dados apresentados no slide anterior segue uma especificação chamada JSON; • Notação de Objetos JavaScript (JavaScript Object Notation), ou simplesmente JSON; A ideia é
manter a simplicidade para transferir as informações, suportando tipos de dados bem simples:
Tipo de dado Valor
Null Valor vazio
Boolean true ou false
Number Número com sinal que pode ter uma notação com E exponencial String Sequência de um ou mais caracteres Unicode
Object Um array não ordenado com itens do tipo chave-valor, onde todas as chaves devem ser strings distintas no mesmo objeto
Array Lista ordenada de qualquer tipo, inteira entre colchetes e com cada elemento separado por vírgulas.
JSON
• Exemplo de JSON:
JSON não padroniza o formato de data, ou como trabalhar com
BSON
• O MongoDB trabalha com o BSON (Binary JSON) que tem suporte para os formatos abaixo:
Tipo de dado Valor
MinKey, MaxKey,
Timestamp tipos utilizados internamente no MongoDB. BinData Array de bytes para dados binários.
ObjectID Identifcador único de um registro do MongoDB.
Date Representação de data.
Uso de banco de dados
Instalando o MongoDB
• Baixe o zip com os arquivos em: https://www.MongoDb.org/downloads
• Descompacte o conteúdo na pasta c:\mongodb\ • Crie o diretório aonde ficarão os dados c:\data\db • Crie o diretório aonde ficarão os logs c:\data\log
• Crie uma variável de ambiente conforme figura ao lado:
• Para executar o serviço do MongoDB, abra um prompt de comandos e execute o comando a seguir: C:\mongodb\bin\mongod.exe
• Para efetuar uma conexão ao MongoDB, abra outro prompt de comandos e execute o comando listado a seguir: C:\mongodb\bin\mongo.exe Você verá o prompt do mongodb
Instalando o MongoDB
• Toda a vez que estivermos usando o mongo precisamos deixar um cmd aberto com o servidor e outros para nossa base!
• A não ser se instalarmos um serviço, assim nunca iremos precisar abrir outro cmd e digitar mongod por que ele estará como serviço.
Testando a instalação
•
Digite o comando
db.version()
no prompt de comando
Digite exit para fechar a conexão cliente
Conceitos básicos
•
O MongoDB é um
document database
(banco de dados de
documentos), mas não são os documentos da família Microsoft, mas
documentos com informações no formato JSON. A ideia é o
documento representar toda a informação necessária, sem a restrição
dos bancos relacionais.
•
Os documentos são agrupados em
collections
.
Conceitos básicos
•
Se for necessário, esse database pode ser duplicado em outros
servidores, e cada cópia é chamada de replica set (conjunto de
réplica).
Uma replica set rs1 que contém dois databases, e cada um deles possui duas collections.Conceitos básicos
•
Sharding
(particionamento), que é usado quando sua collection
passou dos bilhões de registros e há vantagem em dividir os dados
por servidor
Uma collection única de três terabytes que pode ser particionada em três partições de
um terabyte cada, espalhada em três máquinas distintas.
Importando dados para o MongoDB
•
Importando os dados da mega sena do site da Caixa Econômica Federal:
mongoimport
-c <nome-da-collection> --type csv
--headerline <nome-do-arquivo-CSV>
Neste exemplo dos dados da Mega-Sena, os parâmetros são:
mongoimport -c megasena --type csv --headerline megasena.csv
Importando dados para o MongoDB
• Em um banco relacional tradicional, para qualquer carga de dados é necessário criar a estrutura (a tabela). No MongoDB não precisa de nada disso: a collection megasena foi criada automaticamente.
Estatísticas no MongoDB
• db.help()• Lista todos os comandos que podem ser aplicados no banco de dados e contém também uma explicação (guarde este comando no coração);
• show dbs
• Mostra todos os bancos de dados existentes no servidor.
• show collections
• Mostra todas as coleções de um banco de dados existentes no servidor.
• db
• Mostra qual banco de dados está sendo usado. Se você acabou de instalar o MongoDB, e executar este comando verá que o banco de dados usado é o test, banco de dados default e para testes do
MongoDB
• use nomeBD
• Este comando acessa um determinado banco de dados, quando ele existe. Se o banco não existe ele é criado automaticamente.
Estatísticas no MongoDB
Buscar registros
• Para exibir todos os registros de uma collection, usamos o comando find:
Buscar registros
Buscar registros
• Usando o comando findOne, é exibido apenas o primeiro registro:
• Fazendo analogia aos bancos de dados relacionais, temos:
Note que existe um campo chamado _id, ele é conhecido como ObjectId, o qual é inserido automaticamente pelo MongoDB e garante a
Buscar registros
• O comando find pode receber parâmetros para filtrar o resultado:
• Fazendo analogia aos bancos de dados relacionais, temos:
Buscar registros
• O sufixo pretty formata a saída do JSON:
> db.<nome-da-collection>.find({<campo1>:<valor1>,..., <campo N>:<valor N>}).pretty()
O _id, não e é sequencial, ele é um timestamp da máquina.
Filtrando os jogos que tiveram 5 ganhadores.
Buscar registros
• O comando find pode explicitar quais campos serão exibidos:
• Fazendo analogia aos bancos de dados relacionais, temos:
db.<nome-da-collection>.find( {<campo1>:<valor1>,..., <campo N>:<valor N>}, {<campo1>:<exibeOuNãoExibe>,....}
)
Podemos informar true/false ou 1/0.
O ObjectId é sempre visível, logo temos que explicitar a
Inserindo registros
• O comando insert adiciona registro na coleção:
> db.<nome-da-collection>.insert({<campo1>:<valor1>,..., <campo N>:<valor N>})
Instrução parecida com SQL tradicional
Inserindo registros
• Vamos armazenar os ganhadores dos concursos da mega sena.
Não é preciso criar a estrutura da tabela
• Vamos armazenar os ganhadores dos concursos da mega sena com campos diferentes.
Inserindo registros
Podemos também alterar a estrutura da
• Vamos armazenar os ganhadores dos concursos da mega sena com campos diferentes.
• Inserindo explicitamente o ObjectId
Inserindo registros
Temos dados com estruturas diferentes na
mesma collection
Inserindo valores únicos no ObjectId
• O comando update atualiza registros.
• O comando update apresenta um comportamento diferente de um banco relacional. Além de atualizar registros, com ele é possível também alterar a estrutura de uma collection e até remover colunas.
Atualizando registros
db.<nome-da-collection>.update( {<CritérioDeBusca>:<valor1>,...},
{<campoParaAtualizar1>}:<novoValor1>,....} )
• Utilizando comando update para atualizar registros.
Atualizando registros
Consultei o registro pelo id
Como comportamento padrão, as colunas não informadas são
eliminadas.
• Utilizando comando update para atualizar registros sem apagar os campos.
Atualizando registros
db.<nome-da-collection>.update( {<CritérioDeBusca>:<valor1>,...},
{ $set{<campoParaAtualizar1>}:<novoValor1>}} )
Com o comando set, os campos nãosão eliminados.
• O comando update atua sempre no primeiro registro. Para que ele altere todos os
registros é preciso adicionar mais um parâmetro booleano, o multi, que por questões de segurança tem o valor padrão como false.
Atualizando registros
Alterei todos os registros semo parâmetro multi.
Alterei todos os registros como parâmetro multi. Todos registros alterados. Apenas o primeiro registros
• O comando update tem também o parâmetro upsert. Ele indica que o registro será atualizado se ele existir, caso contrário ele será cadastrado.
Atualizando registros
Atualizo um registro que não existe
Atualizo um registro que não existe, mas com o parâmetro upsert
O registro inexistente é inserido.
Existem dois registros
• O comando remove retira registros das coleções
Removendo registros
Removido o ganhador com o CPF informado
db.<nome-da-collection>.remove( {<CritérioDeBusca>:<valor1>,...} )
Removido todos os registros da collection
• O comando drop remove uma collection da base de dados
Removendo registros
db.<nome-da-collection>.drop()
• O comando update remove colunas de uma collection
Removendo colunas
db.<nome-da-collection>.update({}, { $unset: {<campo>: 1} }, false, true)
O parâmetro false avisa que não é um upsert e o parâmetro true é a confirmação para remover em todos os documentos, e não apenas no primeiro.
• O comando update também altera o nome colunas de uma collection
Alterando o nome das colunas
db.<nome-da-collection>.update({}, { $rename: {<CampoAtual>: <NovoCampo>} }, false, true)
A diretiva rename é responsável por alterar o nome da coluna
• Buscando dados utilizando expressões regulares
Melhorando as buscas
db.<nome-da-collection>.find( { <campo>: /<Texto-para-busca>/ } ) ou
db.<nome-da-collection>.find( { <campo>: {$regex: <Texto-para-busca>})
Funciona inclusive com datas.
Melhorando as buscas
Operadores Função
$gt maior que (greater-than)
$gte igual ou maior que (greater-than or equal to)
$lt menor que (less-than)
$lte igual ou menor que (less-than or equal to)
$ne não igual (not equal)
$in existe em uma lista
$nin não existe em uma lista
$all existe em todos elementos
$not traz o oposto da condição
$mod calcula o módulo
$exists verifica se o campo existe $elemMatch compara elementos de array
• A normalização evita a redundância de dados armazenados, mas ela pode ser um
problema quando for necessário consultar essas informações separadas em várias tabelas.
• As várias tabelas, podem estar mais espalhadas no disco rígido e, provavelmente, exigirá mais processamento da CPU para juntar tudo ao retornar para uma consulta.
• Quando se trabalha com MongoDB, a primeira coisa para se considerar é como a aplicação precisa dos dados agrupados
• Perceba que sempre a forma como a aplicação necessita das informações é essencial para organizar as suas collections, ela é a chave de uma boa performance de seu sistema.
Projeto de banco de dados
Relacionamento 1:N (Duas collections)Criamos um campo na collection de Comentários referenciando a chave primária da collection Livros,
isso simula uma chave estrangeira. Entretanto, não tem nenhuma
Projeto de banco de dados
Relacionamento N:N (Duas collections)Vinculamos também os livros às categorias, isso simula uma tabela
intermediária. Essa abordagem tambémnão traz nenhuma vantagem para o MongoDB.
• Se tudo ficar em uma collection, há a vantagem de termos as informações de maneira mais intuitiva e melhor performance.
Projeto de banco de dados
Tudo em uma collection (Exemplo real) Em uma base de dados relacional teríamos o seguinte schema para um sistema de controle de filmes.• Como todo sistema relacional, esse modelo foi criado levando em conta apenas as formas normais, sem levar em consideração como a aplicação foi montada.
No MongoDB, fazemos uma análise inicial da aplicação e a partir dela montamos o nosso schema de collections. Percebemos que a aplicação como um todo exige:
• Busca por atores; • Busca por filmes;
• Exibir todas informações de um ator; • Exibir todas informações de um filme.
Portanto, percebemos que tudo dentro de uma mesma collection é a melhor solução, já que a aplicação não faz nenhuma consulta complexa que necessite separar as informações.
• Para fazer uma busca mais abrangente, com mais opções, vamos usar a sintaxe um pouco diferente:
Buscas avançadas
Operadores relacionaisdb.<nome-da-collection>.find( { <campo>: {<operador>: <valor1>} } ).count()
Vamos usar o operador count apenas para simplificar os resultados
• O operador DISTINCT elimina as repetições do resultado de uma consulta:
Buscas avançadas
Resultados distintosExistem jogos com esses números de ganhadores na base de dados.
• Podemos aplicar expressões regulares às consultas:
Buscas avançadas
Expressões regularesEncontra valores numéricos em um campo de texto.
db.<nome-da-collection>.find( { <campo>: {$regex: <máscara>} } ).count()
• Os operadores lógicos and, nor, not e or trabalham de maneira semelhante ao habitual:
Buscas avançadas
Operadores lógicosdb.<nome-da-collection>.find( { <operador-lógico>: [<condição1>, <condição2>,...] } ).count()
• O operador exists verifica a existência de um campo:
Buscas avançadas
Operador unárioApenas um registro tem o campo “obs” nessa collection
• O operador like existente nos bancos de dados relacionais permitem fazer buscas por trechos de texto, o MongoDB tem um similar que é o “/”:
Buscas avançadas
Operador similar ao likeTodos os seriados que tem o trecho de texto “ad”.
• Para a busca sem considerar maiúsculas ou minúsculas é preciso colocar “i” (case insensitive)
Buscas avançadas
Operador similar ao like• Para buscar por palavras que terminam com um trecho de caracteres é preciso colocar “$”
Buscas avançadas
Operador similar ao likeTrecho de texto que terminam com “ad”
• Para buscar por palavras que se iniciam com um trecho de caracteres é preciso colocar “^”
Buscas avançadas
Operador similar ao likeTrecho de texto que começam com “Br”
• Para ordenar o resultado da consulta, usamos o sufixo sort, especificando as colunas que desejamos ordenar em ordem crescente (com o valor 1):
Buscas avançadas
Ordenando os registrosNomes por ordem decrescente
• Para limitar os resultados pode-se usar o comando limit informando a quantidade de documentos que devem ser exibidos:
Buscas avançadas
Limitando registrosRetorna apenas um registro
• Além de limitar os registros, pode-se informar com o comando skip a quantidade de documentos que serão desconsiderados (escapados) antes de exibir:
Buscas avançadas
Saltando registrosRetorna apenas um registro pulando os
• Para incrementar um valor armazenado em algum campo do registro deve-se utilizar o comando inc:
Buscas avançadas
Incrementando valoresIncrementado o salário do funcionário
com o _id informado em R$500,00
Datas
•
Existe um objeto especial para representar datas no MongoDb
•
A formatação de data não utiliza Locales, assim a aplicação cliente
que deve formatar a data de forma correta.
•
A manipulação das datas foi concebida de forma parecida com o
Javascript.
Datas
Código digitado no prompt do mongo• Apresentação criada espelhando o livro: