Artigo do tipo Tutorial
Recursos especiais neste artigo:
Conteúdo sobre boas práticas.
Desvendando as consultas ao MongoDB
Este artigo aborda formas de consulta a dados tanto pelo Mongo Shell quando pela linguagem Java. Neste contexto, são apresentadas consultas dos tipos simples e avançadas, o uso do framework de agregação e também da classe QueryBuilder. Não menos importante, o artigo aborda ainda formas de conhecer o desempenho individual de cada consulta ao banco, assim como o uso de índices para melhorar o desempenho.

Em que situação o tema é útil
Este tema é útil para quem deseja começar a utilizar o banco de dados MongoDB e está interessado em informações sobre desempenho e formas de desenvolver suas consultas.

Atualmente os bancos de dados NoSQL (Not Only SQL) passaram a estar em evidência entre aplicações de grande porte e grandes empresas que utilizam de algum modo o ambiente web, estão aderindo com muito entusiasmo a este novo modelo. Esta escolha está sendo feita por consequência de alguns fatores positivos oferecidos pelas soluções NoSQL em relação aos bancos relacionais. Dentre estes fatores temos uma maior velocidade na pesquisa dos dados, menor espaço físico em disco para armazenamento e fácil escalabilidade, o que permite distribuir o banco de dados em várias máquinas fazendo uso do particionamento de dados, também conhecido como Sharding.

Em busca de fatores positivos como estes, grandes empresas já aderiram ao NoSQL, como a Google, Facebook, Twitter, Amazon.com, MTV Networks, Disney IMG, Cisco, entre outras. No Brasil, há algum tempo, em um evento sobre o banco de dados NoSQL MongoDB, o especialista Franklin Amorim da Globo.com revelou que o MongoDB foi o banco de dados escolhido para o jogo online CartolaFC. Atualmente essa é a maior aplicação da Globo.com, com mais de dois milhões de usuários cadastrados e com um pico de aproximadamente 90 milhões de páginas visualizadas em Junho de 2011. Normalmente, em seus projetos, a empresa usa como base de dados relacional o MySQL e a equipe da Globo.com revelou que encontrou algumas vantagens no uso do MongoDB sobre o MySQL. Entre elas, são citadas: a velocidade superior (2x mais rápida que o MySQL), o acesso mais natural aos dados e a possibilidade de escalar a escrita de dados com Sharding (sistema de compartilhamento do MongoDB) – leia mais sobre isso no endereço indicado na seção Links.

O MongoDB é um banco de dados livre, desenvolvido pela empresa Norte Americana 10gen. O banco foi desenvolvido sobre o conceito de documentos e coleções, onde cada coleção armazena vários documentos. Nessa arquitetura poderíamos tentar relacionar uma coleção a uma tabela e um documento a uma linha da tabela. Mas existem algumas diferenças bem significativas entre elas como, por exemplo, o MongoDB não possui relacionamento entre coleções, como existe entre tabelas de um banco relacional; os documentos são considerados dinâmicos, ou seja, você pode ter um documento com cinco campos ao mesmo tempo em que há outros com três ou seis campos, por exemplo; ao invés de ter um relacionamento entre tabelas, é possível usar o conceito de documentos embutidos, ou seja, um documento dentro do outro.

Os documentos no MongoDB seguem o padrão JSON (JavaScript Object Notation), e após serem persistidos são transformados em BSON, um tipo de dado binário e serializado próprio do MongoDB. Com o formato dos documentos em JSON, a manipulação dos dados é realizada com base em chave (key) e valor (value), o que torna possível o dinamismo entre documentos. Se, por exemplo, em uma coleção qualquer, um novo documento a ser inserido conter entre suas chaves uma chave de valor nulo ou vazio, não é preciso inserir esta chave. Entretanto, em um momento futuro, quando existir um valor para tal chave, basta alterar o documento inserindo a chave e o valor e apenas este documento irá sofrer as alterações. Caso novas chaves sejam necessárias, em virtude da necessidade de armazenar alguma nova informação, elas podem ser inseridas nos documentos conforme cada documento sofrer alguma alteração como, por exemplo, um update. Já em um banco de dados relacional, você não teria essa facilidade, e precisaria criar uma instrução SQL de alteração da tabela para inserir uma nova coluna. Caso a nova coluna não tenha qualquer valor em algumas linhas, ela receberia o valor “null” nestas linhas. Este espaço na coluna ocupado pelo “null” seria mantido pelo SGDB para um futuro dado, o que acaba consumindo espaço físico em disco, e se este dado nunca for inserido, então se perde muito espaço em disco armazenando apenas o valor “null”.

No entanto o objetivo do artigo não será salvar documentos ou testar o espaço gasto em disco para armazená-los, e sim, explorar diretamente as queries, ou métodos de consultas a dados a partir de código Java e também pelo Shell do MongoDB. Dentre os métodos de consulta temos as consultas simples (Simple Queries), consultas avançadas (Advanced Queries), o framework de agregação (Aggregation Framework) e consultas do tipo QueryBuilder.

Todos esses tipos consultas serão apresentados no artigo por meio de exemplos práticos em Java e também no mongo Shell. Além disso, será demonstrado como alcançar um melhor desempenho nas consultas com a adição de índices na coleção de documentos e veremos também as ferramentas oferecidas pelo MongoDB para avaliação de desempenho das queries. Uma coleção com inúmeros documentos será disponibilizada ao leitor para download, a qual será usada como exemplo para os testes das queries, juntamente com o código fonte Java utilizado no projeto.

Conhecendo a coleção Users

A coleção Users contém os dados que serão usados como exemplo, na execução das queries, durante todo o artigo. Para obter esta coleção é necessário acessar a seção de downloads da Java Magazine, baixar o conteúdo (arquivo contendo a coleção) e fazer a importação para o banco de dados MongoDB. Os passos para realizar a importação serão demonstrados na seção “Dependências do Projeto”.

Antes de importar esta coleção, no entanto, é importante conhecer a estrutura dos documentos que ela armazena. Para isso, observe a Listagem 1. Note que o documento é idêntico a qualquer documento JSON, onde se tem um nome para a chave (key) e um determinado valor (value) para esta chave. Neste exemplo é possível observar que a chave _id possui o valor 8, representando o identificador do documento, equivalente, por exemplo, à chave primária (PK) de uma tabela em bancos de dados relacionais.

O identificador no MongoDB, conforme definido por padrão, será sempre precedido por um underline. No documento da coleção Users, existem outros campos além do _id, como as chaves name e age. A chave info é o que chamamos de documento interno (embedded document), ou sub-documento. Este tipo de documento normalmente é composto por pelo menos uma nova chave interna, e pode substituir a necessidade de se criar uma nova coleção para armazenar as informações contidas nele.

Na coleção Users, info possui as chaves internas hometown e job. Outra forma de armazenar dados em um documento Mongo é usando arrays, como exemplificado na chave preferences. Esta chave armazena valores sobre as preferências do usuário, como se fossem tags encontradas em sistemas de blog que identificam os principais assuntos de uma postagem.

Os documentos da coleção Users foram gerados através de um processo randômico, podendo assim possuir documentos contendo nenhuma ou varias preferências para cada usuário. Isto foi feito propositalmente para que o leitor veja que um documento Mongo não precisa ter a estrutura idêntica a todos os outros documentos da coleção, como acontece, por exemplo, em tabelas de bancos de dados relacionais, onde todas as linhas de uma tabela sempre terão todas as colunas.

Listagem 1. Exemplo de um documento da coleção Users.


{
          "_id" : 8,
          "name" : "Rodrigo Miranda Radel",
          "age" : 70,
          "info" : {
                  "hometown" : "Joao Pessoa",
                  "job" : "Comediante"
          },
          "preferences" : [
                  "Automobilismo",
                  "Basquete",
                  "Robotica"
          ]
  }

Agora observe a Listagem 2. Pode-se notar que o documento apresentado não possui a chave preferences, já que o usuário não tem nenhuma preferência adicionada. Esta é uma grande vantagem encontrada no MongoDB que faz reduzir o consumo físico de memória no disco rígido. Se um campo não é utilizado, ao invés de ter este campo com um valor vazio ou mesmo nulo, ocupando um espaço sem uma informação significante, é mais vantajoso não adicioná-lo no documento. Pode ser que para um banco de dados com dezenas, ou mesmo centenas de registros esta diferença nem seja percebida, mas quando trabalhamos com milhares ou milhões de dados, a soma de vários campos sem informação alguma pode acabar resultando em muito espaço físico desperdiçado. E como um documento Mongo é considerado dinâmico, a qualquer momento é possível realizar uma alteração neste documento e inserir as preferências do usuário. Tenha em mente que qualquer chave de um documento da coleção Users pode ser omitido, exceto a chave _id, por possuir o mesmo papel de uma chave primária em bancos relacionais.

Listagem 2. Documento sem a chave preferences.


{
          "_id" : 16,
          "name" : "Daniela Pinho Milito",
          "age" : 58,
          "info" : {
                  "hometown" : "Alagoinhas",
                  "job" : "Carpinteiro"
          }
  }

Dependências do projeto

Por causa das dependências do projeto que será construído neste artigo, serão necessários alguns downloads e também a instalação do banco de dados MongoDB, como também a importação da coleção Users. Para realizar o download do banco de dados, acesse o endereço referente na seção Links e faça o download da versão 2.2.2, conforme o seu sistema operacional. Faça também o download do mongo-java-driver.jar, a API fornecida pelo MongoDB para acesso Java ao banco de dados, o qual deverá ser adicionado a sua aplicação. A URL para download do driver versão 2.10.1, usada no artigo, também pode ser encontrada na seção Links.

A instalação do banco de dados é muito simples, bastando realizar os seguintes passos (exemplo em Windows):

· Faça a descompactação do arquivo baixado;

· Copie o conteúdo extraído para o diretório c:\;

· Para facilitar a execução das instruções futuras na linha de comando, altere o nome da pasta raiz descompactada para “mongo”;

· Entre no diretório c:\mongo\bin e copie todos os arquivos existentes. Cole estes arquivos em c:\mongo;

· Crie um novo diretório chamado “data” dentro do diretório c:\mongo. Este novo diretório será onde o MongoDB irá armazenar o banco de dados.

Importando a coleção Users

Chegou o momento da importação da coleção Users para o MongoDB. Para isso, descompacte o arquivo users.rar e copie o seu conteúdo (users.json) para o diretório c:\mongo. Em seguida abra uma janela do console do seu sistema operacional e navegue até o diretório c:\mongo. Antes da importação da coleção, no entanto, devemos inicializar o MongoDB executando o seguinte comando:

c:\mongo> mongod --dbpath data

O comando mongod é o responsável por inicializar o MongoDB, e o parâmetro ––dbpath indica ao MongoDB onde está armazenado o banco de dados, que neste caso é no diretório data. Se a inicialização ocorreu com sucesso, você terá um retorno no console semelhante ao exibido na Listagem 3.

Listagem 3. Log de inicialização.


Thu Jan 03 16:52:19 [initandlisten] MongoDB starting : pid=4352 port=27017
 dbpath=data 64-bit host=MarcioBallem-PC
  Thu Jan 03 16:52:19 [initandlisten] db version v2.2.0, pdfile version 4.5
  Thu Jan 03 16:52:19 [initandlisten] git version:
 f5e83eae9cfbec7fb7a071321928f00d1b0c5207
  Thu Jan 03 16:52:19 [initandlisten] build info: 
  windows sys.getwindowsversion
 (major=6, minor=1, build=7601, platform=2, 
  service_pack='Service Pack 1')
 BOOST_LIB_VERSION=1_49
  Thu Jan 03 16:52:19 [initandlisten] options: { dbpath: "data" }
  Thu Jan 03 16:52:19 [initandlisten] journal dir=data/journal
  Thu Jan 03 16:52:19 [initandlisten] recover : 
  no journal files present, no recovery needed
  Thu Jan 03 16:52:22 [initandlisten] waiting 
  for connections on port 27017
  Thu Jan 03 16:52:22 [websvr] admin web console waiting for 
  connections on port 28017 ... 

Quer ler esse conteúdo completo? Tenha acesso completo