↓ Arquivos ↓

Categorias → noSQL

Primeiros passos NoSQL com MongoDB: manipulando documentos

Continuando meu post anterior sobre o assunto, é hora de colocarmos a teoria em prática. Meu objetivo agora é expor o básico sobre o funcionamento e operação do MongoDB para que, em seguida, possamos aplicar este SGBD a alguma linguagem de programação (muito provávelmente usarei o Groovy, que cai como uma luva).

Instalando o Servidor

De todos os SGBDs não relacionais que experimentei, aquele com qual tive mais facilidade para trabalhar foi o MongoDB por duas razões: ele é realmente simples e a documentação é excelente. A facilidade do sistema se apresenta no primeiro contato que temos com a criatura: instalando-o.

Simples e rápido: baixe a versão que se adequa ao seu sistema operacional neste link. Descompacte-o em um diretório de sua escolha e o bicho está quase pronto para ser usado.

Para iniciar o servidor, você deverá executar o programa mongod, presente no diretório $MONGODB/bin (entenda $MONGODB como sendo o diretório aonde você descompactou a sua distribuição do programa). Você será saudado por uma nada simpática mensagem de erro na qual encontrará um texto similar ao abaixo:

Thu Apr 15 21:32:54 Assertion: 10296:dbpath (/data/db/) does not exist

Isto ocorre porque por default o MongoDB armazena seus bancos de dados no diretório /data/db (C:\data\db se estiver usando Windows). A solução é simples: ou você cria este diretório ou inicia o processo mongod com o parâmetro -dbpath como no exemplo abaixo:

$mongodb/bin/mongod -dbpath=/home/kicolobo/mongodb

Neste caso, estou instruindo o servidor a buscar pelos arquivos de banco de dados dentro do diretório /home/kicolobo/mongodb

Nota: é importante mencionar que se eu inicio o MongoDB usando a abreviação ~ para o meu diretório home (por exemplo: ~/mongodb) o processo mongod não identifica o diretório, retornando aquela mesma entediante mensagem de erro (ao menos no Mac OS X).

Observação importante: caso você esteja usando uma versão de 32 bits do MongoDB, esta possuirá o tamanho dos bancos de dados limitados a no máximo 2 Gb.

Conectando-se

O cliente nativo do MongoDB é o programa mongo, localizado no diretório $MONGODB/bin. Com o servidor em execução, caso você inicie este aplicativo automáticamente já estará logado no servidor default, que é o local usando a porta 27017. Não é necessário prover um usuário (posso falar mais sobre gerenciamento de usuários em um post futuro no entanto). Ao iniciar o shell você será saudado por um prompt similar ao exposto na imagem abaixo:

Neste podemos fazer basicamente tudo o que quisermos com o MongoDB. Por default, estamos conectados ao banco de dados test. Para mudar de banco de dados, basta usar o comando use seguido do nome do banco de dados. Por exemplo use kico;.

Manipulando dados

Inserindo

No MongoDB, cada banco de dados é composto por um conjunto de coleções. O código abaixo, apesar de muito simples nos diz muita coisa:


> use kico
switched to db kico
> a = {posicao:1, descricao:"Primeira letra do alfabeto"}
{ "posicao" : 1, "descricao" : "Primeira letra do alfabeto" }
> db.alfabeto.save(a)
> a
{
 "posicao" : 1,
 "descricao" : "Primeira letra do alfabeto",
 "_id" : ObjectId("4bc7b65da5ec5e132c1a53a1")
}

A primeira coisa que fiz foi selecionar o banco de dados kico usando o comando use. Se este banco de dados não existisse, o MongoDB o criaria automaticamente para nós.

Em seguida, criei uma variável chamada a, cujo valor é uma estrutura no formato JSON composta por dois atributos: posicao e descricao. Lembre-se que estamos lidando aqui com um SGBD schemaless: sendo assim posso criar documentos com o formato que eu sonhar.

(Por possuir um shell baseado em JavaScript, é possível escrever scripts e usá-los para tarefas de manutenção do banco. Trata-se de um recurso fantástico que, um dia, pretendo abordar com maiores detalhes neste blog.)

Para inserir o meu documento a em uma coleção, usei o objeto db, que aponta para o banco de dados atualmente selecionado. A sintaxe para inclusão de um registro é simples:

db.[nome da coleção].save( objeto a ser salvo )

No caso, estou incluindo o documento a dentro da coleção alfabeto. Assim como no caso do banco de dados, se esta coleção não existir no banco de dados atual, esta será criada automaticamente no momento em que o primeiro documento for inserido.

Claro, eu também poderia incluir um novo registro na coleção alfabeto tal como no exemplo abaixo:

db.alfabeto.save({posicao:5, letra:"e"})

Finalmente, expus o conteúdo do documento a após ter sido incluido na coleção. Observe a inclusão de um novo atributo neste objeto: o _id .Como o próprio nome já diz, um identificador interno usado pelo MongoDB para diferenciar os objetos armazenados em nossas coleções. É importante mencionar que este atributo só será criado pelo MongoDB caso ainda não exista na estrutura a ser armazenada. Sendo assim, você é livre para criar seus próprios identificadores se quiser.

Editando e excluindo

Editar um registro também é fácil. Novamente, vamos analisar um código bem simples que nos dirá bastante coisa:


documento = db.alfabeto.findOne({posicao:1})
documento.bobagem = "Veja, estou incluindo um novo atributo completamente inútil!"
db.alfabeto.save(documento)
db.alfabeto.remove(documento)

O primeiro passo foi usar o método findOne presente na nossa coleção alfabeto. Este recebe como parâmetro um fragmento de documento e, como o próprio nome já nos diz, retorna um único resultado para nós.

Dai pra frente é simples: adiciono um novo atributo ao nosso documento e em seguida o persisto novamente na coleção usando o mesmo método save() que vimos anteriormente. A diferença é que aqui será feita uma substituição, visto que o documento em questão já possui um atributo _id.

Nota importante: você pode dar o nome que sonhar para um atributo, porém duas regras devem ser satisfeitas: O nome do atributo não deve começar com o caractere $ e o caractere ‘.’ jamais poderá ser incluido.

Continuando

No próximo post (que pretendo publicar nesta semana) vou mostrar como fazer consultas no MongoDB. Não inclui este conteúdo agora porque tornaria este post gigantesco e não trataria com o detalhamento que desejo o assunto.

Sendo assim, aguardem pelo próximo post sobre o assunto. Até lá!

Introdução ao MongoDB: um banco de dados NoSQL

Já faz algum tempo que venho estudando o MongoDB.  Dentro da turma dos SGBDs NoSQL este foi aquele com o qual acabei criando maior simpatia pela sua simplicidade e documentação (apesar de muita gente falar do Apache Cassandra, sua documentação ainda é horrível).

O MongoDB é um banco de dados orientados a documentos. Sendo assim, se você, assim como eu (e 99% dos desenvolvedores) vêm de um ambiente dominado pelo modelo relacional, em um primeiro momento verá este SGBD como um alienígena – o que é incrívelmente empolgante e assustador. Meu objetivo neste post não é ensinar a usar o MongoDB (será assunto do próximo), mas sim expor as principais diferenças entre este e o confortável modelo relacional.

Este assustador (e maravilhoso) “mundo novo”

Para os acostumados com o modelo relacional, o MongoDB se mostrará assustador no primeiro contato porque a maior parte dos conceitos que nos forneciam uma certa sensação de segurança basicamente “desaparecem”. Aqui é obrigatório saber lidar com o medo: conforme mostrarei neste post, há riscos, mas os ganhos os compensam.

Não acho que o modelo não relacional possa ser aplicado a todos os casos, porém é sempre importante conhecer mais de um paradigma para que possamos no mínimo ampliar nossos horizontes quando nos deparamos com situações que fogem da nossa zona de conforto (e o MongoDB pode ser bastante desconfortável neste primeiro momento).

Não há registros, mas documentos

Algo sempre me incomodou no modelo relacional: com ele tentamos representar o mundo real (que é n-dimensional) usando uma abordagem bidimensional. Tudo o que eu for representar em minhas tabelas possui apenas duas dimensões: linhas e colunas. É verdade que podemos representar quantas dimensões quisermos no modelo relacional a partir de relacionamentos, porém sempre fica aquela sensação de se estar “forçando a barra”.

Além disto, por mais bem feita que seja o processo de análise, sempre há a possibilidade de posteriormente mais um atributo ser encontardo. O mundo é um ambiente complexo: acredito que para representá-lo, precisamos também de uma terminologia complexa.

No MongoDB, o equivalente aos registros são os documentos, que utilizam a sintaxe JSON. A melhor maneira de se ter um feeling do que quero dizer é ver o bicho. Sendo assim, observe o código abaixo:


Kico = {
nome: "Henrique Lobo Weissmann",
apelido: "Kico (ou seria este o nome?)",
cidade: "Belo Horizonte"
}

Eu criei um documento chamado kico que possui 3 atributos: nome, apelido e cidade. Repare que em momento algum defini o tamanho máximo de cada atributo, regras de validação ou qualquer tipo de restrição. Em seguida, se quiser armazená-lo em um banco de dados, bastaria executar o código abaixo:


db.kicodb.save(Kico)

Neste caso, eu estaria armazenando o documento Kico no banco de dados kicodb. Agora, observe o código abaixo:


Nanna = {nome:"Maria Angélica Alvares da Silva e Silva",
apelido:"Nãnna",
esposaDo:"Kico",
cidade:{nome:"Belo Horizonte", estado:{nome:"Minas Gerais", pais:"Brasil"}},
caes:[{nome:"Fraude", raça:"Pinscher?"}, {nome:"Zé", raça:"Schnauzer"}]}

db.kicodb.save(Nanna)

Repare que um registro com estrutura completamente diferente foi incluida no banco de dados. Até o atributo cidade é diferente. Enquanto no registro “Kico” eu tenho apenas uma string, no objeto Nanna eu tenho um outro documento. Outro ponto interessante: repare que eu tenho inclusive uma coleção associada ao objeto Nanna.

E tudo é mesmo assim salvo no mesmo banco de dados sem problema algum. Na realidade, eu poderia armazenar até o registro abaixo sem problemas:


esquisitao = {quantidade:34, poemaFavorito:"Batatinha"}

Como pode ser visto, não há regras de validação rígidas: qualquer tipo de documento pode ser armazenado no banco de dados. Claro: na prática somente objetos semelhantes são armazenados na base de dados, porém é bacana saber que se um dia aparecer algum novo atributo, poderemos inclui-lo apenas nos documentos aonde o mesmo é necessário, ao contrário do modelo relacional, aonde uma coluna se aplica a todos os registros.

Desvantagem: o desenvolvedor precisa ficar esperto para que suas bases de dados não virem um “samba do criolo doido”

Vantagens:

  • Finalmente você se livrou de uma abordagem bidimensional e pode representar objetos do mundo real como realmente são: complexos e únicos.
  • Caso no futuro surja algum caso no qual novos atributos apareçam, você pode aplicá-los somente aonde é necessário, e não em todos os casos, como no modelo relacional, aonde normalmente cria-se uma nova “coluna” na tabela relacionada

Redundância de dados máxima

No modelo relacional somos o tempo inteiro incentivados a reduzir ao máximo possível a redundância de dados. Aliás, os relacionamentos existem justamente para isto. E é um modelo que inegávelmente funciona muito bem. Já no MongoDB a situação é inversa: não há relacionamentos, e a duplicação de dados, pelo que pude observar é até incentivada.

Dê uma olhada no código abaixo:


pessoa1 = {nome:"Peçonhento", cidade:{nome:"Belo Horizonte", estado:"MG"}}

pessoa2 = {nome:"Zequinha", cidade:{nome:"Belo Horizonte", estado: "MG"}}

pessoa3 = {nome:"Joca", cidade:"Lagoa Santa"}

pessoa4 = {nome:"Complexado", cidade:{nome:"Rio de Janeiro", estado:{nome:"Rio de Janeiro", pais:{nome:"Brasil"}}}

Lembre-se de que aqui não há tabelas: há coleções de documentos. Em cada documento armazeno os dados da forma que eu quiser. Eu poderia criar uma coleção contendo apenas cidades e em seguida criar um relacionamento entre duas ou mais coleções distintas, é verdade (foge do assunto deste post), mas isto iria contra a idéia básica por trás do modelo orientado a documentos.

A idéia básica aqui é a de que um documento deve ser auto-contido, ou seja, isolado já deve conter todas as informações de que necessita. Por que isto? Simples: porque assim você ao invés de fazer uma consulta com vários joins como é o caso do modelo relacional executa uma única consulta, que já te retorna o documento inteiro. Resultado: mais performance.

Desvantagem: se você quiser alterar todos os registros relacionados a uma unidade semântica, precisa tratá-los um a um

Vantagem: maior performance. Uma única consulta já te retorna tudo o que você precisa saber a respeito do documento. Esta é uma das razões pelas quais vêm sendo adotado em projetos que exigem alta performance.

Concluindo

Estas são as duas principais diferenças (que só são vantagens de acordo com o caso) que vi no MongoDB (do modelo baseado em documenots na realidade) com relação ao modelo relacional. É aplicado a todos os casos? Óbvio que não.

O importante a meu ver é sair da área de conforto do modelo relacional: isto, como mencionei, amplia os nossos horizontes, faz com que vejamos outras possibilidades além de tabelas para armazenar nossos dados. Fico assustado quando topo com desenvolvedores que só conseguem desenvolver algo que envolva tabelas, colunas e registros. Aliás, a grande vantagem que vejo nesta “moda” de modelos noSQL é justamente esta: a exposição de “novos” paradigmas a um mundo dominado pelo modelo relacional, que só considero ruim quando tomado como a única alternativa viável pela maior parte das pessoas.

Este post é fundamental para que eu possa partir para os próximos, nos quais exporei como usar o MongoDB e, ainda mais importante, como aplicá-lo com Groovy e Java. Grande abraço!

Ah, quer baixar o MongoDB? Este é o site oficial: http://www.mongodb.org

Get Adobe Flash playerPlugin by wpburn.com wordpress themes