Explore o MongoDB

Saiba por que esse sistema de gerenciamento de bancos de dados é tão popular

Neste artigo, aprenderemos sobre o MongoDB, o sistema de gerenciamento de banco de dados de software livre e orientado a documentos, escrito em C++, que fornece recursos para a escalada de seus bancos de dados em um ambiente de produção. Descubra os benefícios que os bancos de dados orientados a documentos têm em relação aos tradicionais sistemas de gerenciamento de banco de dados relacionais (RDBMS). Instale o MongoDB e comece a criar bancos de dados, coleções e documentos. Examine os recursos de consulta dinâmica do Mongo, que fornecem eficiência de armazenamento de chave/valor de uma maneira familiar a administradores e desenvolvedores de bancos de dados RDBMS.

Joe Lennon, Lead Mobile Developer, Core International

Joe Lennon photoJoe Lennon é desenvolvedor de software de Cork, Irlanda. Ele trabalha como desenvolvedor de aplicativos para a Web e Oracle PL/SQL na Core International, e se formou pela Universidade College Cork em 2007 em sistemas de informações comerciais.



11/Jul/2011

O que é o MongoDB?

Nos últimos anos, vimos um interesse crescente em sistemas de gerenciamento de bancos dados que diferem do modelo relacional tradicional. No centro disso está o conceito de NoSQL, um termo usado coletivamente para denotar software de banco de dados que não usa SQL (Structured Query Language) para interagir com o banco de dados. Um dos projetos NoSQL mais notáveis até o momento é o MongoDB, uma banco de dados orientado a documentos e de software livre que armazena dados em coleções de documentos semelhantes a JSON. O que distingue o MongoDB de outros bancos de dados NoSQL é a sua poderosa linguagem de consulta baseada em documento, que torna a transição de um banco de dados relacional para o MongoDB fácil, porque as consultas são convertidas com bastante facilidade.

O MongoDB é escrito em C++. Ele armazena dados dentro de documentos semelhantes a JSON (usando BSON — uma versão binária de JSON), que retém os dados usando pares de chave/valor. Um recurso que diferencia o MongoDB de outro bancos de dados de documentos é que é muito simples converter instruções SQL em chamadas de função de consulta do MongoDB. Isso facilita a migração de organizações que atualmente usam bancos de dados relacionais fazerem a migração. Ele também é muito simples de instalar e usar, com binários e drivers disponíveis para os principais sistemas operacionais e linguagens de programação.

O MongoDB é um projeto de software livre, com o banco de dados em si licenciado sob a GNU AGPL (Affero General Public License) versão 3.0. Essa licença é uma versão modificada da GNU GPL que fecha uma brecha na qual as restrições de copyleft não se aplicam ao uso do software, mas apenas à sua distribuição. Isso, naturalmente, é importante em software armazenada na nuvem e geralmente não instalado em dispositivos cliente. Usar a GPL regular poderia resultar em alguém perceber que nenhuma distribuição de fato acontece e, portanto, potencialmente contornar os termos da licença.

A AGPL aplica-se apenas ao próprio aplicativo de banco de dados, e não a outros elementos do MongoDB. Os drivers oficiais que permitem que os desenvolvedores conectem o MongoDB a várias linguagens de programação são distribuídos sob a Licença Apache, Versão 2.0. A documentação do MongoDB está disponível sob a licença Creative Commons.

Bancos de dados orientados a documentos

Os bancos de dados orientados a documentos são bastante diferentes dos tradicionais bancos de dados relacionais. Em vez de armazenar dados em estruturas rígidas, como tabelas, eles os armazenam em documentos vagamente definidos. No caso de tabelas de sistemas de gerenciamento de bancos de dados relacionais (RDBMS), se for preciso acrescentar uma nova coluna, será necessário mudar a definição da própria tabela, que acrescentará aquela coluna a todos os registros existentes (embora potencialmente com valor nulo). Isso se deve ao estrito design baseado em esquema do RDBMS. No entanto, em documentos, é possível acrescentar novos atributos aos documentos individuais sem que outros sejam alterados. Isso porque o design de bancos de dados orientados a documentos costuma ser sem esquema.

Outra diferença fundamental é que bancos de dados orientados a documentos não fornecem relacionamentos estritos entre documentos, o que ajuda a manter seu design sem esquema. Isso difere muito de bancos de dados relacionais, que dependem fortemente de relacionamentos para normalizar o armazenamento de dados. Em vez de armazenar dados "relacionados" em uma área de armazenamento separada, em bancos de dados de documentos eles são integrados ao próprio documento. Isso é muito mais rápido do que armazenar uma referência a outro documento onde os dados relacionados são armazenados, visto que cada referência exigiria uma consulta adicional.

Isso funciona muito bem para muitos aplicativos nos quais faz sentido os dados ficarem autocontidos dentro de um documento pai. Um bom exemplo (encontrado também na documentação do MongoDB) são posts e comentários de blogs. Os comentários se aplicam somente a um único post, de modo que não faz sentido separá-los dele. No MongoDB, seu documento de post de blog teria um atributo comments para armazenar esses comentários referentes a esse post. Em um banco de dados relacional provavelmente haveria uma tabela de comentários com uma chave de ID primária, uma tabela de posts com uma chave de ID primária e uma tabela de mapeamento intermediária post_comments que definiria que comentários pertencem a qual post. Isso é muito complexo, desnecessariamente, para algo que deveria ser muito simples

Contudo, se for preciso armazenar dados relacionados em separado, é possível fazer isso facilmente no MongoDB usando uma coleção separada. Outro bom exemplo é armazenar informações de pedidos de clientes em documentos do MongoDB. Geralmente isso inclui informações sobre o cliente, o próprio pedido, itens de linha do pedido e informações sobre o produto. Usando o MongoDB, provavelmente seriam armazenados os clientes, produtos e pedidos em coleções individuais, mas seriam integrados dados de itens de linha dentro do documento de pedido relevante. Seria então feito referência às coleções products e customers usando IDs em estilo de chave estrangeira, assim como faria em um banco de dados relacional. A simplicidade dessa abordagem híbrida faz do MongoDB uma escolha excelente para quem está acostumado a trabalhar com SQL. Isso posto, tire tempo e tome cuidado para decidir a abordagem que precisará ser usada em cada caso de uso individual, visto que os ganhos de desempenho podem ser significativos ao incorporar os dados dentro do documento, em vez de fazer referência a eles em outras coleções.

Visão rápida dos recursos

MongoDB é muito mais do que apenas um armazenamento básico de chaves/valores. Vamos dar uma breve olhada em algum de seus recursos:

  • Binários oficiais disponíveis para Windows®, Mac OS X, Linux® e Solaris, distribuição de código de origem disponível para autoconstrução
  • Drivers oficiais disponíveis para C, C#, C++, Haskell, Java™, JavaScript, Perl, PHP, Python, Ruby e Scala, com uma ampla variedade de drivers suportados pela comunidade disponíveis para outras linguagens
  • Consultas JavaScript ad-hoc que permitem localizar dados usando qualquer critério de qualquer atributo de documento. Essas consultas são um espelho da funcionalidade de consultas SQL, o que torna muito fácil para desenvolvedores SQL escreverem consultas em MongoDB.
  • Suporte a expressões regulares em consultas
  • Os resultados da consulta em MongoDB são armazenados em cursores que fornecem muitas funções para filtragem, agregação e classificação, incluindo limit(), skip(), sort(), count(), distinct() e group().
  • map/reduce -- implementação para agregação avançada
  • Armazenamento de arquivos grandes usando GridFS
  • Suporte a indexação de atributo semelhante a RDBMS, onde é possível criar índices diretamente em atributos selecionados de um documento
  • Recursos de otimização de consulta usando dicas, planos de explicação e perfis
  • Replicação mestre/escravo similar ao MySQL
  • Armazenamento de objeto baseado em coleta, permitindo consulta referencial onde forem necessários dados normalizados
  • Escalada horizontal com auto-sharding
  • Atualizações no local para simultaneidade de alto desempenho e livre de disputas
  • Shell on-line que permite testar o MongoDB sem instalá-lo
  • Documentação detalhada, com vários livros publicados e outros sendo escritos

Instalando o MongoDB

Felizmente, o MongoDB é muito simples de instalar em uma grande variedade de plataformas. Estão disponíveis distribuições binárias para Windows, Mac OS X, Linux e Solaris, enquanto diversos gerenciadores de pacotes oferecem instalação fácil e opções de configuração para outros sistemas. Para quem é corajoso, é possível compilar o código de origem sozinho. Nesta seção, aprenderemos a instalar o MongoDB em Windows e Mac OS X, definindo o processo como serviço no Windows ou como daemon no OS X.

Instalando no Windows

A instalação do MongoDB no Windows é muito simples. No seu navegador da Web favorito, acesse http://www.mongodb.org/downloads e faça o download do mais recente release de produção estável para Windows. Recomendamos a versão de 64 bits, mas ela só pode ser usada se estivermos utilizando o sistema operacional Windows de 64 bits. Em caso de dúvida, basta usar a versão de 32 bits.

Extraia o arquivo zip na unidade C:\, o que criará uma nova pasta chamada mongodb-win32-i386-1.6.4, ou algo assim. Para facilitar a sua vida, renomeie essa pasta para mongo. Depois, é preciso criar um diretório de dados. No Windows Explorer, vá até a raiz da unidade C:\ e crie uma pasta chamada data. Dentro dela, crie outra pasta chamada db.

Agora é possível iniciar o servidor do MongoDB. Use o Windows Explorer para navegar até C:\mongo\bin e dê dois cliques em mongod.exe. Feche a janela de prompt de comando que aparece para parar o servidor do MongoDB. Ou seja, é mais conveniente configurar o servidor do MongoDB como um serviço que o Windows controle. Vamos fazer isso.

Abra uma janela de prompt de comando (Start>Run>, digite cmd e pressione OK) e dê os comandos da Listagem 1.

Listagem 1. Configuração do servidor do MongoDB como serviço
> cd \mongo\bin
> mongod --install --logpath c:\mongo\logs --logappend 
--bind_ip 127.0.0.1 --directoryperdb

É possível ver o resultado na Listagem 2.

Listagem 2. Serviço criado com êxito
all output going to c:\mongo\logs
Creating service MongoDB.
Service creation successful.
Service can be started from the command line via 'net start "MongoDB"'.

Com o Mongo instalado como serviço, é possível iniciá-lo com o seguinte comando: > net start "MongoDB"

É possível ver o resultado na Listagem 3.

Listagem 3. Mongo iniciado com êxito
The Mongo DB service is starting.
The Mongo DB service was started successfully.

Agora é possível executar o cliente de shell do MongoDB. Se a janela de prompt de comando estiver aberta, confirme se está na pasta c:\mongo\bin folder e digite o seguinte comando: > mongo.

Como opção, no Windows Explorer navegue até C:\mongo\bin e dê dois cliques em mongo.exe. Não importa sua opção para iniciar o shell, deve aparecer um prompt semelhante à Listagem 4.

Listagem 4. Iniciando o shell
MongoDB shell version: 1.8.1
connecting to: test
>

A menos que também queira configurar o MongoDB em uma máquina com Mac OS X, pule para a próxima parte desta seção e passe para "Guia de Introdução", onde aprenderemos a interagir com o servidor do MongoDB usando o cliente de shell.

Instalando no Mac OS X

Supondo que esteja em uso a versão de 64 bits do Mac OS X, as etapas seguintes fornecem detalhes de como fazer o download do binário do MongoDB para OS X de 64 bits, extraí-lo e configurá-lo para começar. Também mostrará como executar o MongoDB como um daemon.

Primeiro, execute o Terminal (Applications>Utilities>Terminal). Na janela do Terminal, execute os comandos encontrados na Listagem 5.

Listagem 5. Configurando o MongoDB no Mac OS X
$ cd ~
$ curl http://fastdl.mongodb.org/osx/mongodb-osx-x86_64-1.6.4.tgz > mongo.tgz
$ tar xzf mongo.tgz
$ mv mongodb-osx-x86_64-1.8.1/ mongo
$ mkdir -p /data/db

O MongoDB está configurado e pronto para uso. Antes de prosseguir, pode ser bom adicionar o MongoDB ao seu caminho. Execute o seguinte comando: $ nano ~/.bash_profile.

Talvez esse arquivo ainda não exista. Seja como for, acrescente a seguinte linha: export PATH={$PATH}:~/mongo/bin.

Salve o arquivo pressionando ctrl + O e depois aperte Enter no prompt. Em seguida, pressione ctrl + X para sair do nano. Agora, carregue novamente seu perfil bash com o seguinte comando: $ source ~/.bash_profile.

Agora, está tudo pronto para inicializar o MongoDB. Para isso, basta dar o seguinte comando: $ mongod.

Isso iniciará o servidor de banco de dados do MongoDB como processo em primeiro plano. Se for preferível iniciar o MongoDB como processo daemon em segundo plano, use o seguinte comando: $ sudo mongod --fork --logpath /var/log/mongodb.log --logappend.

Será solicitada uma senha; digite sua senha de administrador do Mac OS X nesse prompt.

Independentemente de qual método for escolhido para iniciar o MongoDB, o servidor deverá estar em execução. Se tiver sido iniciado em primeiro plano, será preciso uma guia Terminal separada ou uma janela para iniciar o cliente. Para iniciá-lo, basta usar o comando: $ mongo

Deve aparecer o prompt da Listagem 6.

Listagem 6. Iniciando o cliente
MongoDB shell version: 1.8.1
connecting to: test
>

Na próxima seção, aprenderemos a usar o shell do MongoDB para criar bancos de dados, coleções, documentos, e assim por diante.


Guia de introdução para o uso do MongoDB

Incluído com a distribuição do MongoDB há um aplicativo de shell que permite o controle completo sobre seus bancos de dados. Usando o shell, é possível criar e gerenciar bancos de dados, coleções, documentos e índices usando funções JavaScript do lado do servidor. Isso facilita começar a usar o MongoDB rapidamente. Nesta seção, aprenderemos a iniciar o shell e verem os exemplos de alguns comandos básicos para fazer o armazenamento e a recuperação básicos de dados.

Shell do MongoDB

O aplicativo de shell do MongoDB está incluído na distribuição deste, na pasta bin. No Windows, está na forma do aplicativo mongo.exe. Dê dois cliques nesse programa no Windows Explorer para iniciar o shell. Em sistemas operacionais baseados em UNIX® (incluindo o Mac OS X) inicie o shell do MongoDB executando o comando mongo na janela de terminal (desde que tenham sido seguidas as instruções acima para acrescentar o diretório do MongoDB no seu caminho).

Quando o shell é aberto pela primeira vez, aparece a mensagem da Listagem 7.

Listagem 7. Mensagem após abrir o shell
MongoDB shell version: 1.8.1
connecting to: test
>

A conexão com seu servidor MongoDB local estará pronta, em especial, com o banco de dados "test". Na próxima seção, aprenderemos a criar bancos de dados, documentos e coleções. Se em qualquer momento for preciso obter ajuda, basta dar o comando "help" na linha de comando do shell do Mongo A Figura 1 mostra a saída típica de um comando de ajuda.

Figura 1. Saída do comando help do shell do Mongo
Saída do comando help do shell do Mongo

Se quiser ver o código de origem por trás de uma função do MongoDB, basta digitar o nome da função no shell, e ele imprimirá o código de origem em JavaScript. Por exemplo, digite connect e pressione a tecla Enter para ver o código de origem usado para se conectar a um banco de dados do MongoDB.

Criando bancos de dados, coleções e documentos

Por padrão, o shell do Mongo se conecta ao banco de dados "test". Para mudar para outro banco de dados, use o comando "use dbname". Se o banco de dados não existir, o MongoDB o criará assim que forem incluídos dados nele. Vamos mudar para o banco de dados "mymongo" com o seguinte comando: > use mymongo.

O shell deve apresentar a mensagem: switched to db mymongo.

Nesse ponto, o banco de dados ainda não existe, porque não contém dados. No MongoDB, os dados são armazenados em coleções, permitindo separar documentos, se necessário. Vamos criar um documento e armazená-lo em uma nova coleção chamada "colors": > db.colors.save({name:"red",value:"FF0000"});.

Vamos verificar se o documento foi armazenado procurando o banco de dados: > db.colors.find();.

Deve aparecer uma resposta similar à seguinte (o atributo _id é um identificador exclusivo e provavelmente será diferente no seu resultado): { "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "red", "value" : "FF0000" }.

Os documentos no MongoDB são armazenados como BSON (JSON binário). Usando o shell do Mongo, podemos inserir dados utilizando uma sintaxe semelhante à JSON, na qual cada documento é um objeto de pares de chave/valor. Nesse exemplo, criamos um documento com dois atributos: name e valor, que têm os valores red e FF0000 (a representação hexadecimal da cor vermelha padrão), respectivamente.

Como talvez tenha notado, não é preciso predefinir a coleção colors ; isso é feito automaticamente ao inserir um item usando a função save.

Nesse exemplo, criamos um documento bem simples. Contudo, a sintaxe semelhante à JSON usada também pode ser utilizada para criar documentos mais complexos. Veja o seguinte documento JSON, que representa uma ordem de compra ou fatura (consulte a Listagem 8).

Listagem 8. Criando um documento simples
{
    order_id: 109384,
    order_date: new Date("12/04/2010"),
    customer: {
        name: "Joe Bloggs",
        company: "XYZ Inc.",
        phone: "(555) 123-4567"
    },
    payment: {
        type: "Cash",
        amount: 4075.99,
        paid_in_full: true
    },
    items: [
        {
            sku: "ABC1200",
            description: "A sample product",
            quantity: 1,
            price_per_unit: 75.99,
        }, {
            sku: "XYZ3400",
            description: "An expensive product",
            quantity: 2,
            price_per_unit: 2000
        }
    ],
    cashier_id: 340582242
}

Como se pode ver, esses documentos podem armazenar vários tipos de dados, incluindo cadeias de caractere, números inteiros, flutuantes, datas, objetos, arrays, e muito mais. Na Listagem 8, os itens do pedido foram integrados diretamente ao documento da ordem, agilizando a recuperação dessas informações ao consultar o documento posteriormente.

Visto que o shell do MongoDB usa JavaScript, é possível escrever construções regulares em JavaScript ao interagir com os bancos de dados. Veja a Listagem 9, que cria uma coleção de documentos de caracteres, cada um contendo a representação da cadeia de caractere do caractere e seu código ASCII associado.

Listagem 9. Criando uma coleção de documentos de caracteres
> var chars = "abcdefghijklmnopqrstuvwxyz"
> for(var i =0; i<chars.length; i++) {    
... var char = chars.substr(i, 1);          
... var doc = {char:char, code: char.charCodeAt(0)};
... db.alphabet.save(doc);
... }

Este loop criará 26 documentos, um para cada letra minúscula do alfabeto, cada documento contendo o caractere em si e seu código de caractere ASCII. Na próxima seção, veremos como recuperar esses dados de várias maneiras.

Recuperando dados

Na última seção, não só aprendemos a inserir dados em um banco de dados do MongoDB, mas também a usar a função mais básica de recuperação de dados, find. Vamos começar usando o comando find na coleção de alfabeto que criamos no final da seção anterior: db.alphabet.find();.

Isso deve gerar uma resposta semelhante à Listagem 10.

Listagem 10. Resposta gerada
> db.alphabet.find()
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8c"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8d"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8e"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8f"), "char" : "d", "code" : 100 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec90"), "char" : "e", "code" : 101 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec91"), "char" : "f", "code" : 102 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec92"), "char" : "g", "code" : 103 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec93"), "char" : "h", "code" : 104 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec94"), "char" : "i", "code" : 105 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec95"), "char" : "j", "code" : 106 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec96"), "char" : "k", "code" : 107 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec97"), "char" : "l", "code" : 108 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec98"), "char" : "m", "code" : 109 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec99"), "char" : "n", "code" : 110 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9a"), "char" : "o", "code" : 111 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9b"), "char" : "p", "code" : 112 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9c"), "char" : "q", "code" : 113 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9d"), "char" : "r", "code" : 114 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9e"), "char" : "s", "code" : 115 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9f"), "char" : "t", "code" : 116 }
has more
>

Por padrão, a função find() recupera todos os documentos da coleção, mas exibe apenas os 20 primeiros documentos. O comando it recuperará os 6 documentos restantes (veja a Listagem 11).

Listagem 11. Recuperando os 6 documentos restantes
> it
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca0"), "char" : "u", "code" : 117 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca1"), "char" : "v", "code" : 118 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca2"), "char" : "w", "code" : 119 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca3"), "char" : "x", "code" : 120 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca4"), "char" : "y", "code" : 121 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca5"), "char" : "z", "code" : 122 }
>

A função find() na verdade, retorna um cursor para o conjunto de resultados da consulta, nesse caso retrieve all documents. Quando isso não é atribuído a uma variável ou não são executadas outras funções, por padrão será impresso um conjunto de resultados de amostra na tela. Para exibir todo o conjunto de resultados, podemos usar o seguinte comando: > db.alphabet.find().forEach(printjson);.

Isso imprime todos os registros no conjunto de resultados, em vez de exibir um subconjunto. A seguir, veremos mais sobre como usar cursores e consultas para filtrar dados.


Consultando dados

Um dos maiores pontos fortes do MongoDB é seu suporte poderoso a consulta ad-hoc que funciona mais ou menos da mesma maneira que em bancos de dados relacionais tradicionais, embora filtre e retorne documentos BSON em vez de linhas da tabela. Essa abordagem o destaca em relação a outros armazenamentos de documentos, que muitas vezes são difíceis para que desenvolvedores SQL se familiarizem. Com o MongoDB, consultas SQL relativamente complexas podem ser facilmente convertidas em chamadas de função JavaScript. Nesta seção, aprenderemos as várias funções disponíveis que permitem consultar os dados no MongoDB, e como configurar índices para ajudar a otimizar suas consultas, como se faria de forma semelhante em DB2, MySQL ou Oracle.

Consultas básicas

Na seção anterior, aprendemos a usar a função find para recuperar todos os documentos. A função find aceita uma série de argumentos que permitem filtrar os resultados retornados. Por exemplo, na coleção de alfabeto que criamos anteriormente, é possível encontrar todos os registros em que o atributo "char" tem valor "q" com o seguinte comando: > db.alphabet.find({char: "o"});.

Isso retorna a seguinte resposta: { "_id" : ObjectId("4cfa4adf528bad4e29beec9a"), "char" : "o", "code" : 111 }.

Se quisermos retornar todos os caracteres com código menor ou igual a 100, podemos usar o seguinte comando: > db.alphabet.find({code:{$lte:100}});.

Isso retorna o resultado na Listagem 12, como é de esperar.

Listagem 12. Resultado
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8c"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8d"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8e"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8f"), "char" : "d", "code" : 100 }

O MongoDB suporta uma variedade de operadores condicionais, incluindo:

  • $lt (menor que)
  • $lte (menor ou igual a)
  • $gt (maior que)
  • $gte (maior ou igual a)
  • $all (corresponder a todos os valores em um array)
  • $exists (verificar se um campo existe ou não)
  • $mod (módulo)
  • $ne (não igual)
  • $in (corresponder a um ou mais valores em um array)
  • $nin (corresponder a valores zero em um array)
  • $or (corresponder uma consulta a outra)
  • $nor (não corresponder uma consulta nem outra)
  • $size (corresponder qualquer array com número definido de elementos)
  • $type (corresponder valores com tipo de dados BSON especificado)
  • $not (não igual a)

Para obter mais detalhes sobre todos esses operadores, consulte a documentação do MongoDB (veja Recursos para obter um link).

É possível restringir os campos que são retornados por suas consultas usando um segundo argumento na função find. Por exemplo, a seguinte consulta retornará apenas o atributo char para qualquer documento com valor de código entre 102 e 105: > db.alphabet.find({code:{$in:[102,103,104,105]}}, {char: 1});.

Isso deve produzir o resultado da Listagem 13.

Listagem 13. Resultado
{ "_id" : ObjectId("4cfa4adf528bad4e29beec91"), "char" : "f" }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec92"), "char" : "g" }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec93"), "char" : "h" }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec94"), "char" : "i" }

Na próxima seção, aprenderemos a criar índices para agilizar suas consultas.

Indexação

Os índices em MongoDB são bem similares aos dos bancos de dados relacionais. É possível colocar um índice em qualquer atributo. Além disso, campos indexados podem ser de qualquer tipo de dados, incluindo objeto ou array. Como no caso de índices de RDBMS, é possível criar índices compostos usando vários atributos e índices exclusivos, que garantem que valores duplicados não sejam permitidos.

Para criar um índice básico, use a função ensureIndex . Agora vamos criar um índice nos atributos code e char na coleção de alfabeto (veja a Listagem 14).

Listagem 14. Criando um índice
> db.alphabet.ensureIndex({code: 1});
> db.alphabet.ensureIndex({char: 1});

É possível soltar índices usando as funções dropIndex e dropIndexes. Veja a documentação do MongoDB para obter mais informações.

Classificação

Para classificar seu conjunto de resultados, é possível aplicar a função sort ao seu cursor. Nossa coleção de alfabeto já está classificada em ordem crescente pelos atributos code e char, então vamos obter um subconjunto de volta em ordem crescente, ordenada pelo atributo code: > db.alphabet.find({code: {$gte: 118}}).sort({code: 0});.

Isso retorna o resultado na Listagem 15.

Listagem 15. Resultado
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca5"), "char" : "z", "code" : 122 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca4"), "char" : "y", "code" : 121 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca3"), "char" : "x", "code" : 120 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca2"), "char" : "w", "code" : 119 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca1"), "char" : "v", "code" : 118 }

Se o argumento foi fornecido {code: 1} à função sort no comando anterior, os resultados devem ter sido classificados em ordem crescente. Para garantir consultas de alto desempenho, certifique-se de adicionar um índice a qualquer atributo que usar para classificar dados.


Resultados de paginação usando skip e limit

Muitas vezes, ao lidar com conjuntos de resultados de dados, só queremos recuperar um subconjunto por vez, talvez para fornecer resultados por página da Web. Em MySQL, em geral fazemos isso usando a palavra-chave LIMIT . É fácil replicar essa funcionalidade no MongoDB usando as funções skip e limit. Para retornar os primeiros cinco documentos na coleção de alfabeto, podemos executar a seguinte operação: > db.alphabet.find().limit(5);.

Isso retorna o resultado na Listagem 16.

Listagem 16. Resultado
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8c"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8d"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8e"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8f"), "char" : "d", "code" : 100 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec90"), "char" : "e", "code" : 101 }

Para obter a próxima página, use o seguinte comando: > db.alphabet.find().skip(5).limit(5);.

Como é possível ver na Listagem 17 , isso obtém os próximos cinco registros.

Listagem 17. Obtendo os próximos cinco registros
{ "_id" : ObjectId("4cfa4adf528bad4e29beec91"), "char" : "f", "code" : 102 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec92"), "char" : "g", "code" : 103 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec93"), "char" : "h", "code" : 104 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec94"), "char" : "i", "code" : 105 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec95"), "char" : "j", "code" : 106 }

Funções de grupo e agregação

O mecanismo de consulta do MongoDB também torna muito simples aplicar agregação e funções de grupo aos seus dados. Isso é análogo aos seus equivalentes em SQL. Comprovadamente, a função mais utilizada é a count(): > db.alphabet.find().count();.

Isso deve retornar 26. É possível contar consultas filtradas com a mesma facilidade: > db.alphabet.find({code: {$gte: 105}}).count();.

A instrução acima deve retornar 18.

Outra função de agregação útil é distinct. Ela é usada para retornar um conjunto de valores distintos para um atributo. Nossa coleção de alfabeto é um exemplo ruim visto que todos os dados são únicos, por isso, vamos acrescentar alguns registros à coleção colors que criamos no início deste artigo (veja a Listagem 18).

Listagem 18. Acrescentando registros à coleção color
> db.colors.save({name:"white",value:"FFFFFF"});
> db.colors.save({name:"red",value:"FF0000"});  
> db.colors.find();

Supondo que a coleção colors não tenha sido excluída, deve aparecer a resposta da Listagem 19.

Listagem 19. Response
{ "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "red", "value" : "FF0000" }
{ "_id" : ObjectId("4cfa5830528bad4e29beeca8"), "name" : "white", "value" : "FFFFFF" }
{ "_id" : ObjectId("4cfa5839528bad4e29beeca9"), "name" : "red", "value" : "FF0000" }

Como se pode ver, há claramente dois documentos red nessa coleção. Vamos usar a função distinct para obter um conjunto de valores de atributo name exclusivos dessa coleção: > db.colors.distinct("name");.

Isso retorna o seguinte: [ "red", "white" ].

É importante notar que não executam a função distinct em um cursor ou conjunto de resultados como no caso de outras funções de consulta, mas sim diretamente na coleção. Observe também que ele não retorna um conjunto de documentos, mas sim um array de valores.

O MongoDB também fornece a função group para executar ações como na expressão GROUP BY em SQL. A função group é uma coisa complexa; por isso, só vou dar um exemplo breve aqui. Para o nosso exemplo, digamos que queremos contar o número de documentos agrupados pelo valor de nome. Em SQL, poderíamos definir essa expressão como SELECT name, COUNT(*) FROM colors GROUP BY name;.

Para executar essa consulta em MongoDB, usamos o comando na Listagem 20.

Listagem 20. Usando a função group
> db.colors.group(
... {key: {name: true},
... cond: {},
... initial: {count: 0},                                  
... reduce: function(doc, out) { out.count++; }
... });

Isso produz o resultado na Listagem 21.

Listagem 21. Resultado
[
    {
        "name" : "red",
        "count" : 2
    },
    {
        "name" : "white",
        "count" : 1
    }
]

se for preciso executar agregação avançada ou usar grandes conjuntos de dados, o MongoDB também inclui uma implementação de map/reduce, que permite fazer isso. A função de grupo descrita acima não funciona em instalações de MongoDB com sharding; então se estivermos usando sharding, precisaremos usar map/reduce em vez dessa função.

Atualizando dados existentes

No shell do MongoDB, é muito fácil atualizar documentos. Na coleção colors que criamos anteriormente, tínhamos dois registros para red. Digamos que queiramos tirar um desses registros e mudá-lo para black, com o atributo de valor 000000 (o valor hexadecimal de preto). Primeiro, podemos usar a função findOne para recuperar um único item com o valor red, mudar suas propriedades como necessário e salvar o documento de volta no banco de dados.

Obtenha um único documento com o nome red e armazene-o na variável blackDoc : > var blackDoc = db.colors.findOne({name: "red"});.

A seguir, usamos a notação dot para alterar as propriedades do documento (veja a Listagem 22).

Listagem 22. Alterando as propriedades do documento
> blackDoc.name = "black";
> blackDoc.value = "000000";

Antes de salvar, vamos verificar se o documento parece certo (deve ter um atributo _id ; caso contrário, vai apenas inserir um novo registro em vez de salvar sobre o registro red): > printjson(blackDoc);.

Se isso retornar algo similar à Listagem 23 estamos prontos para prosseguir.

Listagem 23. Resultado
{
    "_id" : ObjectId("4cfa43ff528bad4e29beec57"),
    "name" : "black",
    "value" : "000000"
}

Por fim, usamos a função save para salvar o documento de volta na coleção colors no banco de dados: > db.colors.save(blackDoc);.

Agora podemos usar a função find para confirmar se nossa coleção parece certa: > db.colors.find();.

Isso deve retornar algo como a Listagem 24. Se aparecerem quatro registros, há algo errado.

Listagem 24. Resultado
{ "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "black", "value" : "000000" }
{ "_id" : ObjectId("4cfa5830528bad4e29beeca8"), "name" : "white", "value" : "FFFFFF" }
{ "_id" : ObjectId("4cfa5839528bad4e29beeca9"), "name" : "red", "value" : "FF0000" }

Fora do shell do Mongo, usamos a função update nos aplicativos para aplicar as mudanças a dados existentes. Para obter mais informações sobre a função update, veja a documentação do MongoDB.

Excluindo dados

Para excluir dados do MongoDB, use a função remove . Note que isso se aplica ao programa de shell do MongoDB; alguns drivers talvez implementem uma função delete ou algo parecido. Verifique a documentação de uma implementação específica se necessário.

A função remove funciona de modo similar à função find. Para remover qualquer documento da coleção colors que corresponda ao nome white, use o seguinte comando: > db.colors.remove({name:"white"});.

Podemos verificar então se esse documento foi removido: > db.colors.find();.

Se estiver tudo certo, deverão aparecer apenas dois documentos (veja a Listagem 25).

Listagem 25. Excluindo dados
{ "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "black", "value" : "000000" }
{ "_id" : ObjectId("4cfa5839528bad4e29beeca9"), "name" : "red", "value" : "FF0000" }

Para remover todos os documentos de uma coleção, basta omitir o filtro do seu comando, como segue: > db.colors.remove();.

Agora, ao tentar usar a função find, não obtemos nenhuma resposta, o que quer dizer que é um conjunto de resultados vazios: > db.colors.find();.

Se houver um documento armazenado em uma variável, também é possível passá-lo para a função remove a fim de excluí-o, mas esse é um modo ineficaz de fazê-lo. Seria melhor localizar o atributo _id desse documento e passá-lo para a função remove .

Para descartar uma coleção, use o seguinte comando: > db.colors.drop();.

Isso retorna o seguinte: true.

Agora podemos verificar se a coleção foi realmente descartada utilizando o comando show collections . Isso deve produzir a saída na Listagem 26.

Listagem 26. Usando o comando show collections
alphabet
system.indexes

Por fim, se quisermos remover um banco de dados inteiro, executamos o seguinte comando: > db.dropDatabase();.

Isso exclui o banco de dados selecionado no momento. Deve aparecer a seguinte saída: { "dropped" : "mymongo", "ok" : 1 }.

É possível usar o comando show dbs para obter uma lista dos bancos de dados disponíveis. mymongo não deve aparecer nessa lista.


Ferramentas e outros recursos

O MongoDB inclui uma série de utilitários para administrar seu banco de dados. Ele oferece vários meios de importação e exportação de dados, para fins de geração de relatórios ou backup. Nesta seção, descobriremos como importar e exportar arquivos no formato JSON, bem como a forma de criar arquivos de hot backup mais eficientes para fins de recuperação. Também aprenderemos a usar as funções map/reduce como alternativa às funções regulares de consulta do Mongo para agregação complexa de dados.

Importando e exportando dados

O diretório bin do MongoDB contém uma série de utilitários para importar e exportar dados em uma variedade de formatos. O utilitário mongoimport permite fornecer um arquivo com cada linha contendo um documento no formato JSON, CSV ou TSV e inserir cada um desses documentos em um banco de dados do MongoDB. Visto que o MongoDB usa BSON, se importarmos documentos JSON, precisaremos fornecer algumas informações de modificador se desejarmos aproveitar qualquer dos tipos de dados adicionais do BSON que não estão disponíveis no JSON regular.

O utilitário mongoexport permite produzir uma saída de arquivo com todos os documentos de um banco de dados do MongoDB representados em formato JSON ou CSV. Isso é útil para a produção de relatórios em que o aplicativo aceita dados JSON ou CSV como entrada. Para produzir um arquivo CSV, é preciso fornecer os campos na ordem em que devem aparecer no arquivo de saída.

Fazer backup e restaurar bancos de dados

Os utilitários mongoimport e mongoexport são úteis para tirar dados do MongoDB para uso em outros aplicativos ou para importar de outros aplicativos que podem disponibilizar dados JSON ou CSV. No entanto, esses utilitários não devem ser usados para fazer backups periódicos ou para restaurar um banco de dados do MongoDB. Visto que o MongoDB usa BSON e não JSON ou CSV, é difícil preservar tipos de dados ao importar dados desses formatos.

Para fornecer funcionalidade adequada de backup e restauração, o MongoDB oferece dois utilitários: mongodump e mongorestore. O mongodump produz um backup de arquivo binário de um banco de dados, e o mongorestore lê esse arquivo e restaura um banco de dados usando-o, criando automaticamente índices conforme a necessidade (a não ser que tenha sido removido o arquivo system.indexes.bson do diretório de backup).


Utilitários de administração

O MongoDB também fornece uma interface de diagnóstico baseada na Web; disponível em http://localhost:28017/ nas configurações padrão do MongoDB. Essa tela é parecida com a captura de tela na Figura 2.

Figura 2. Diagnóstico do MongoDB
Diagnóstico do MongoDB

Para obter informações adicionais sobre administração, execute também os seguintes comandos no shell do MongoDB:

  • db.serverStatus();
  • db.stats();

Se seu servidor do MongoDB travar, repare o banco de dados, verificando se ele foi corrompido e executando compactação de dados. Execute um reparo executando mongod --repair na linha de comando do seu SO, ou então usando o comando db.repairDatabase(); no shell do MongoDB. O último comando é executado em nível por banco de dados, então é preciso executá-lo para cada banco de dados do servidor.

Também é possível validar dados de coleção usando a função de validate. Se houver uma coleção chamada contacts, É possível validá-la com o comando db.contacts.validate();

O MongoDB dispõe de muitos outros recursos para facilitar a vida dos DBAs. Além disso, está disponível uma variedade de ferramentas e interfaces de administração de terceiros. Veja a documentação do MongoDB para obter mais informações.

map/reduce

Quem já usou um banco de dados CouchDB está familiarizado com map/reduce, visto que o mecanismo de visualização usa as funções map/reduce para filtrar e agregar dados por padrão. No MongoDB, não é assim; consultas simples e filtragens (e até agregações) não dependem de map/reduce. Contudo, o MongoDB fornece uma implementação de map/reduce para uso na agregação de grandes conjuntos de dados.

map/reduce provavelmente dariam para um artigo só deles. Para obter informações detalhadas sobre sua implementação no MongoDB, consulte a documentação do MongoDB (veja Recursos para obter um link).


Escalando o MongoDB

Uma razão principal para a recente popularidade de armazenamentos em chave/valor e bancos de dados orientados a documentos é sua cobertura leve e a tendência a ser altamente escalável. A fim de facilitar isso, o MongoDB depende dos conceitos de sharding e replicação, que vamos aprender nesta seção. Além disso, aprenderemos também a armazenar arquivos grandes no MongoDB usando GridFS. Por fim, veremos como criar perfis para suas consultas, otimizando o desempenho do seu banco de dados.

Sharding

Uma parte importante de qualquer infraestrutura de banco de dados é garantir que seja escalável. As implementações do MongoDB são escaladas horizontalmente usando um mecanismo de auto-sharding, permitindo a escalada de uma configuração do MongoDB até milhares de nós, com balanceamento de carga automático, sem ponto único de falha e failover automático. Também é muito simples adicionar novas máquinas a um cluster do MongoDB.

O bom dos recursos de auto-sharding do MongoDB é que simplificam muito ir de um único servidor a um cluster sharded, muitas vezes sendo necessária pouca ou nenhuma alteração no código do aplicativo. Para obter documentação detalhada sobre como o auto-sharding funciona e como implementá-lo, consulte a documentação do MongoDB.

Replicação

O MongoDB fornece recursos de replicação em uma configuração mestre-escravo (semelhante ao MySQL) para fins de failover e redundância, garantindo alto nível de consistência entre os nós. Como alternativa, o MongoDB pode usar conjuntos de réplicas para definir um nó como principal a qualquer momento, com outro nó assumindo como principal no caso de falha.

Diferentemente do CouchDB, que usa replicação como base para escalada, o MongoDB usa replicação principalmente para garantir alta disponibilidade, usando nós escravos como réplicas redundantes.

Para obter mais informações sobre a replicação no MongoDB, consulte a documentação (veja Recursos para obter um link).

Armazenamento de grandes arquivos com GridFS

Os bancos de dados do MongoDB armazenam dados em documentos BSON. O tamanho máximo de um documento BSON é de 4MB, porém, o que os torna inadequados para o armazenamento de arquivos e objetos grandes. O MongoDB usa a especificação GridFS para armazenar arquivos grandes, dividindo-os em pedaços menores entre diversos documentos.

A distribuição MongoDB padrão inclui utilitários de linha de comando para acrescentar e recuperar arquivos de GridFS do sistema de arquivos local e para ele. Além disso, todos os drivers de API oficiais do MongoDB suportam GridFS. Par obter mais detalhes, consulte a documentação do MongoDB (veja Recursos).


Conclusão

Neste artigo, aprendemos sobre o sistema de gerenciamento de banco de dados MongoDB e por que é uma das opções que mais cresce na seção NoSQL popular do mercado de DBMS. Aprendemos por que escolher um banco de dados orientado a documentos em vez de um RDBMS tradicional, e os diversos recursos excelentes que o MongoDB tem a oferecer. Aprendemos a instalar e usar o MongoDB para armazenamento e recuperação de dados, e conhecemos as várias ferramentas e opções de escalabilidade que ele proporciona.

Recursos

Aprender

  • Visite o site oficial do MongoDB.
  • Leia a entrada da Wikipédia sobre o MongoDB .
  • Acesse a documentação oficial do MongoDB.
  • Aprenda mais sobre as funções map/reduce do MongoDB.
  • O MongoDB Cookbook fornece orientações sobre todas as maneiras comuns de usar o MongoDB.
  • Siga o MongoDB no Twitter.
  • Veja o demo do developerWorks "An introduction to MongoDB".
  • Saiba mais sobre Using NoSQL and analyzing big data por meio do caminho de conhecimento do developerWorks.
  • Leia Notes from a production MongoDB deployment para ver como uma empresa mudou de MySQL para o MongoDB.
  • Leia Reflections on MongoDB para saber como a Collective Idea fez a mudança.
  • Leia o blog 12 Months with MongoDB para saber como a Wordnik fez a mudança.
  • Acesse o podcast de Eltot Horowitz (CTO da 10gen, a empresa que patrocina o MongoDB) sobre o MongoDB.
  • 10gen desenvolve e oferece suporte ao MongoDB, o banco de dados de software livre, alto desempenho, escalável e orientado a documentos.
  • Desenvolvimento Java 2.0: MongoDB: Um armazenamento de dados NoSQL com movimentos (apenas os corretos) de RDBMS (Andrew Glover, developerWorks, setembro de 2010): Aprenda tudo sobre a API customizada do MongoDB, seu shell interativo e o suporte a consultas dinâmicas em estilo RDBMS, além de cálculos MapReduce fáceis e rápidos.
  • Explorando o CouchDB (Joe Lennon, developerWorks, março de 2009): O CouchDB de software livre da Apache oferece um novo método de armazenar dados, no que é chamado de modelo de banco de dados orientado a documentos e sem esquema. Em vez do armazenamento de dados altamente estruturado de um modelo relacional, o CouchDB armazena dados de maneira semiestruturada, usando um modelo de visualização baseado em JavaScript para gerar agregação estruturada e resultados de relatórios a partir desses documentos semiestruturados.
  • Eventos interessantes: confira futuras conferências, exposições e webcasts interessantes para desenvolvedores de software livre IBM.
  • Zona de software livre do developerWorks: Encontre muitas instruções, ferramentas e atualizações de projeto para ajudar a desenvolver com tecnologias de software livre e usá-las com produtos IBM.

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=726846
ArticleTitle=Explore o MongoDB
publish-date=07112011