Um pouco de NoSQL com MongoDB

mongodb_mongo_shell

Banco de dados não SQL são um assunto bastante comentado atualmente mas para alguém que vem do mundo relacional a simples ideia de “não ser SQL” soa meio como uma heresia. Você logo fica se perguntando sobre como as informações ficam organizadas, como fazer para consultar os dados etc etc.

Ao menos foi assim comigo e já que resolvi estudar um pouco o assunto e agora sei um pouquinho mais que zero, não custa nada repassar este conhecimento e apresentar como um banco NoSQL funciona, mais especificamente o MongoDB.

Não irei me prender na teoria, a equipe de TI da Leroy Merlin escreveu  um texto bem legal sobre o assunto, explicando o que são bases NoSQL, mostrando as diferenças para o modelo tradicional e contando o caso deles. Vale a pena uma leitura antes de prosseguir.!

MongoDB (“humongous“)

Dentre as opções de bancos de dados NoSQL me aventurei com dois deles, o Redis e o MongoDB. Os dois são bastante parecidos e trabalham como gerenciadores de documentos JSON e a principal diferença deles está no fato de que o Redis somente trabalha com documentos em memória — servidor desligado. dados vão embora — enquanto que o MongoDB eles são persistentes pois são gravados em disco.

O desenvolvimento do MongoDB teve início em 2007 por parte de uma empresa chamada 10gen e com a ideia de criar um serviço. Em 2009 ele foi disponibilizado como software livre (AGPL 3.0) e com a 10gen passando a oferecer suporte comercial e ferramentas. Mais recentemente, em 2013, passaram a se chamar MongoDB Inc.

Assim como o MySQL/MariaDB e outros gerenciadores de bancos de dados o MongoDB tem também um console de comandos mas, diferente de seus “primos” relacionais não existe uma linguagem explícita para manipular as bases de dados e sim funções e métodos. Aliás o console de operação do MongoDB é um interpretador completo de JavaScript.

O MongoDB é um banco de dados sem schema, ou seja, os documentos (o “mesmo” que registros) não precisam seguir uma estrutura pré-definida com tipo e quantidades de campos em uma coleção (o “mesmo” que tabela).

Instalação

A versão padrão do Ubuntu está um pouco defasada, é a 2.6.3 (a versão atual é a 3.0.5) mas para um primeiro contato é mais que suficiente, sendo assim:

$ sudo apt-get install mongodb

Só para verificar se tudo está correto:

$ mongo
MongoDB shell version: 2.6.3
connecting to: test
> _

Interface Web

O MongoDB tem algumas ferramentas de monitoração via console mas como a ideia aqui é apenas apresentar o programa e não criar um ambiente de produção, alguns luxos estão permitidos.

Acrescente estas duas linhas no arquivo “/etc/mongodb.conf”:

...
httpinterface = true
rest = true

Daí reinicie o serviço:

$ sudo service mongodb restart

E acesse a interface  web do servidor, em 127.0.0.1:28017, com seu navegador predileto:

mongodb_web

Não, o Navegador web  do Ubuntu não é o meu navegador predileto, só é mais fácil capturar telas nele 🙂

Fazendo o C.R.U.D.

C.R.U.D. é o acrônimo para create, read, update & delete, ou seja, literalmente: inserir, ler, atualizar e remover as “quatro operações” em um banco de dados (e obviamente dos programas que acessam informações em um banco de dados).

Usarei o próprio console do MongoDB para apresentar os exemplos mas dentro das linguagens de programação, por exemplo em Python via PyMongo, há pouca ou nenhuma alteração na sintaxe.

Inserindo

Para inserir um novo documento em uma coleção usa-se a função insert():

> db.telefones.insert({nome:"Fulano da Silva",telefone:"12345678"})
WriteResult({ "nInserted" : 1 })

E para inserir mais de um documento por vez? Lembra  que o console é Javascript, basta colocar em um array:

> db.«coleção».insert([{«doc»},{«doc»}, ... {«doc»}])

Lendo

A consulta é feita com a função find():

> db.telefones.find().pretty()
{
    "_id" : ObjectId("560432ab9e7f816ccb9fed4d"),
    "nome" : "Fulano da Silva",
    "telefone" : "12345678"
}
{
    "_id" : ObjectId("56045c2e64f4e24c4fee9467"),
    "nome" : "Sicrano de Souza",
    "telefone" : "87654321"
}
{
    "_id" : ObjectId("56045c3e64f4e24c4fee9468"),
    "nome" : "Beltrano Aparecido"
}

Três coisas:

  • A função pretty() serve para deixar a visualização dos documentos mais agradável;
  • Reparem que o terceiro documento não tem campo de “telefone” e
  • Há uma outra função de busca, a findOne(), que retorna somente a o primeiro documento encontrado.

A função find() permite que parâmetros de pesquisa sejam incluídos, por exemplo:

db.telefones.find({ telefone:"12345678" })

Retornará o(s) documento(s) cujo telefone é igual a 1234-5678.

E de onde surgiu este _id?

No MongoDB todo documento precisa possuir um campo _id, tanto que se você não o definir na inserção ele próprio colocará um lá. É o mecanismo usado para distinguir um documento do outro  e, sim, é análogo à chave primária das tabelas relacionais:

> db.telefones.insert({_id:1})
WriteResult({ "nInserted" : 1 })
> db.telefones.insert({_id:1})
WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "insertDocument :: caused by :: 11000 E11000
        duplicate key error index: test.telefones.$_id_  dup
        key: { : 1.0 }"
    }
})

É possível  ainda definir chaves mais complexas como esta aqui, por exemplo:

> db.telefones.find({nome:"Giovanni"}).pretty()
{
    "_id" : {
        "ano" : 2015,
        "mes" : 9,
        "dia" : 1,
        "hora" : 18,
        "minuto" : 31,
        "cliente" : "1234567890"
    },
    "nome" : "Giovanni"
}

Tudo bem, sei que o correto seria fazer um timestamp usando  UNIXTIME mas a ideia é ilustrar a possibilidade (e foi a primeira coisa que veio a cabeça).

Alterando

É feito pela função update() e já que eu esqueci de colocar o telefone do “Beltrano” vamos consertar:

> db.telefones.update({ _id:ObjectId("56045c3e64f4e24c4fee9468") },
  { $set: { profissao:"Dentista" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

E consertado, ou quase:

> db.telefones.find({ _id:ObjectId("56045c3e64f4e24c4fee9468") })
{ "_id" : ObjectId("56045c3e64f4e24c4fee9468"), "nome" : "Beltrano
Aparecido", "profissao" : "Dentista" }

Lembram que o banco não tem schema? Sendo assim posso acrescentar quaisquer campos dentro do documento. O uso do comando $set serve para que eu atualize o campo (caso ele exista) ou insira (caso não exista) dentro do documento.

Veja o que acontece se ele não for utilizado:

> db.telefones.update({ _id:ObjectId("56045c3e64f4e24c4fee9468") },
  { idade:42 })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.telefones.find({ _id:ObjectId("56045c3e64f4e24c4fee9468") })
{ "_id" : ObjectId("56045c3e64f4e24c4fee9468"),
  "idade" : 42 }

Todos os campos que existiam anteriormente, exceto o _id, foram substituídos pelo novo conjunto.

Apagando

E fechando o CRUD, a função para remover documentos, remove():

> db.telefones.count()
3
> db.telefones.remove({ idade:42 })
WriteResult({ "nRemoved" : 1 })
> db.telefones.count()
2

Neste caso removi todos os documentos cuja valor de “idade” fosse 42 (o que poderia remover bem mais do que um único registro).

E, sim, há instruções que acrescentam comparações para igual, diferente, maior, maior que, menor, menor que, e lógico, ou lógico etc.

A função count() serve para totalizar os documentos existentes dentro da coleção.

Finalizando (por ora)

A ideia aqui é só apresentar o MongoDB funcionalmente e apresentando alguns exemplos fáceis de serem replicados. Nem toquei em outros recursos que ele  possui como criação de índices, pesquisas usando coordenadas geográficas, filtro de campos (limitar, ordenar, “desnormalizar”,  etc), réplica da base em vários servidores (replica set — para alta disponibilidade) e segmentação da base (shards) para acelerar o tempo de recuperação.

Sendo assim, até a próxima!

Anúncios

Um comentário sobre “Um pouco de NoSQL com MongoDB

  1. Pingback: Um pouco de NoSQL com MongoDB - Peguei do

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s