Há atualmente na Computação uma onda de adoção de bancos de dados não-relacionais, comumente chamados NoSQL.O foco principal dos bancos NoSQL atuais é a orientação a documentos, uma variação hash da orientação a objetos e alternativa aos RDBMSs, que dominaram a orientação dos gerenciadores de banco de dados por décadas.
O principal banco NoSQL é o CouchDB, DBMS do Projeto Apache baseado em Erlang, porém há uma alternativa bem mais simples e aparentemente tão poderosa quanto: MongoDB.
MongoDB combina os melhores funcionalidades de orientação a documentos, hashes e RDBMSs. É um banco de dados orientado a documentos, escalável, livre de esquema, de alto desempenho e código aberto escrito em C++.
Este artigo dá continuidade ao artigo nas Reflexões de Monte Gasppa e Giulia C. sobre a instalação do MongoDB. Aqui você poderá ver um pouquinho do uso de um banco de dados orientado a documentos.
Este artigo é baseado na documentação oficial e entende que você instalou o MongoDB segundo descrito nas Reflexões de Monte Gasppa e Giulia C..
Conexão na base de dados
Para conectar na base basta usar o comando
mongo:bash$ mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "help" for help
>Caso você tenha configurado uma porta alternativa em
/srv/mongodb/etc/mongodb.conf, você pode especificar isso na linha de comando do cliente:bash$ mongo --port 27018Você também pode se conectar a um servidor remoto, caso ele esteja habilitado para conexão externa, usando a flag
--host.Para escolher qual base de dados usar, o comando é
use:> use mydbAutorização
Você pode se autorizar na linha de comando com as opções
-u (usuário) e -p (senha), ou já do prompt do interpretador:> use admin
> db.auth('admin', 'ra35EG/dz');Comandos básicos
A linguagem de interação com MongoDB é Javascript, mas há alguns comandos úteis no interpretador.
Para listar comandos úteis:
> helpListar recursos uteis da base atual:
> db.help();Listar recursos uteis de uma coleção (levemente equivalente a tabela de um banco relacional), no exemplo
foo:> db.foo.help();Para listar as bases instaladas:
> show dbsPara listar as coleções da base atual:
> show collectionsListar usuários da base atual:
> show usersCriar usuário na base atual:
> db.addUser('admin', 'ra35EG/dz');Autenticar-se:
> db.auth('admin', 'ra35EG/dz');Listar o conteúdo de uma coleção:
> db.foo.find();Apagar uma coleção:
> db.foo.drop();Apagar a base de dados atual:
> db.dropDatabase();Armazenamento de dados
Repare que o MongoDB é livre de esquema, portanto uma coleção pode conter estruturas de dados radicalmente diferentes, sempre no formato JSON.
Por exemplo, vamos inserir dois dados distintos na coleção
foo da base mydb:> use mydb
> var j = { name: 'mongo' };
> var t = { x: 3 };
> db.foo.save(j);
> db.foo.save(t);
> db.foo.find();
{ "_id" : ObjectId("4b8949d9cd50237b8573833b"), "name" : "mongo" }
{ "_id" : ObjectId("4b8949dbcd50237b8573833c"), "x" : 3 }Você não precisa predefinir a coleção, que é criada automaticamente no salvamento da primeira estrutura. O campo
_id é criado automaticamente e é a chave primária.Para apagar o objeto
j:> j = db.foo.findOne({ name: 'mongo' });
> db.foo.remove(j);Para apagar todos os objetos basta remover a coleção:
> db.foo.drop();Vamos usar um pouco mais de lógica:
> for (var i=0; i<100; ++i) db.foo.save({ x: i, y: i*i });Esse loop cria cem registros, com
x variando de zero a noventa e nove e y igual a seu quadrado:> db.foo.find();
{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }
{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }
{ "_id" : ObjectId("4b894c05cd50237b85738342"), "x" : 4, "y" : 16 }
{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }
{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }
{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }
{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }
{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }
{ "_id" : ObjectId("4b894c05cd50237b85738348"), "x" : 10, "y" : 100 }
{ "_id" : ObjectId("4b894c05cd50237b85738349"), "x" : 11, "y" : 121 }
{ "_id" : ObjectId("4b894c05cd50237b8573834a"), "x" : 12, "y" : 144 }
{ "_id" : ObjectId("4b894c05cd50237b8573834b"), "x" : 13, "y" : 169 }
{ "_id" : ObjectId("4b894c05cd50237b8573834c"), "x" : 14, "y" : 196 }
{ "_id" : ObjectId("4b894c05cd50237b8573834d"), "x" : 15, "y" : 225 }
{ "_id" : ObjectId("4b894c05cd50237b8573834e"), "x" : 16, "y" : 256 }
{ "_id" : ObjectId("4b894c05cd50237b8573834f"), "x" : 17, "y" : 289 }
{ "_id" : ObjectId("4b894c05cd50237b85738350"), "x" : 18, "y" : 324 }
{ "_id" : ObjectId("4b894c05cd50237b85738351"), "x" : 19, "y" : 361 }
has moreConsultas (queries)
É possível fazer consultas simples ou bem complexas assim como em modelos relacionais usando MongoDB.
Vamos obter uma contagem de objetos:
> db.foo.find().count();
100Só os cinco primeiros objetos:
> db.foo.find().limit(5);
{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }
{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }Agora os cinco seguintes:
> db.foo.find().skip(5).limit(5);
{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }
{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }
{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }
{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }
{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }Para obter o elemento com valor de
x vinte e quatro:> var e = db.foo.findOne({ x: 24 });
> print(e.y);
576
> print(tojson(e));
{ "_id" : ObjectId("4b894c05cd50237b85738356"), "x" : 24, "y" : 576 }Consultas avançadas
Vamos complicar um pouco…
Para obter todos os registros com
x maior que cinquenta:> db.foo.find('this.x > 50');
{ "_id" : ObjectId("4b894c05cd50237b85738371"), "x" : 51, "y" : 2601 }
{ "_id" : ObjectId("4b894c05cd50237b85738372"), "x" : 52, "y" : 2704 }
{ "_id" : ObjectId("4b894c05cd50237b85738373"), "x" : 53, "y" : 2809 }
{ "_id" : ObjectId("4b894c05cd50237b85738374"), "x" : 54, "y" : 2916 }
{ "_id" : ObjectId("4b894c05cd50237b85738375"), "x" : 55, "y" : 3025 }
{ "_id" : ObjectId("4b894c05cd50237b85738376"), "x" : 56, "y" : 3136 }
{ "_id" : ObjectId("4b894c05cd50237b85738377"), "x" : 57, "y" : 3249 }
{ "_id" : ObjectId("4b894c05cd50237b85738378"), "x" : 58, "y" : 3364 }
{ "_id" : ObjectId("4b894c05cd50237b85738379"), "x" : 59, "y" : 3481 }
{ "_id" : ObjectId("4b894c05cd50237b8573837a"), "x" : 60, "y" : 3600 }
{ "_id" : ObjectId("4b894c05cd50237b8573837b"), "x" : 61, "y" : 3721 }
{ "_id" : ObjectId("4b894c05cd50237b8573837c"), "x" : 62, "y" : 3844 }
{ "_id" : ObjectId("4b894c05cd50237b8573837d"), "x" : 63, "y" : 3969 }
{ "_id" : ObjectId("4b894c05cd50237b8573837e"), "x" : 64, "y" : 4096 }
{ "_id" : ObjectId("4b894c05cd50237b8573837f"), "x" : 65, "y" : 4225 }
{ "_id" : ObjectId("4b894c05cd50237b85738380"), "x" : 66, "y" : 4356 }
{ "_id" : ObjectId("4b894c05cd50237b85738381"), "x" : 67, "y" : 4489 }
{ "_id" : ObjectId("4b894c05cd50237b85738382"), "x" : 68, "y" : 4624 }
{ "_id" : ObjectId("4b894c05cd50237b85738383"), "x" : 69, "y" : 4761 }
{ "_id" : ObjectId("4b894c05cd50237b85738384"), "x" : 70, "y" : 4900 }
has moreOutra opção é usar o operador condicional
$gt:> db.foo.find({ x: { $gt: 50 } });Da mesma forma outros operadores. Por exemplo, todos os elementos com
x entre vinte e três e vinte e seis, inclusive:> db.foo.find('23 <= this.x && this.x <= 26');Ou:
> db.foo.find({ x: { $gte: 23, $lte: 26 } });Os principais operadores são:
$lt– menor que$gt– maior que$lte– menor ou igual a$gte– maior ou igual a$ne– diferente de$in– está em (recebe uma lista)$nin– não está em$mod– resto igual a (recebe uma lista onde o primeiro valor é o divisor e o segundo o resto)$exists– contém ou não o atributo$not– negação de uma condição
Ordenação
A ordenação é feita usando o método
sort. Por exemplo, para ordenar de modo descrescente pelo atributo y:> db.foo.find().sort({ y: -1 });Expressões regulares
Quando há campos com valor string, é possível usar expressões regulares:> db.foo.find({ name: /^mon.o$/i });Índices
Quando você faz muitas consultas baseadas em um determinado atributo, é interessante criar um índice para ele. Por exemplo, se quisermos criar um índice para nosso atributox:> db.foo.ensureIndex({ x: 1 });Obs.¹: o atributo
_id possui índice por padrão.Obs.²: é possível criar índices compostos.
Agregação
Não vou entrar nesse mérito, mas é possível criar agregações, como
GROUP_BY de SQL. Para tanto veja a documentação oficial.Módulos de conexão com linguagens de programação
Há módulos para várias linguagens, que podem ser encontrados na lista de APIs.
O módulo que pude e me fascinou foi para Python. Sua instalação usando
easy_install foi muito simples:bash$ sudo easy_install -U pymongoE seu uso extremamente fácil devido à similiaridade entre dicionários de Python e JSON. A única reclamação que faço é o fato do método
db.auth() do MongoDB ter sido traduzido como db.authenticate() em Python, o que me fez perder alguns segundos tentando entender por que não funcionava.**
Espero que este artigo seja mais do que útil e incite o uso dessa intrigante ferramenta.
[]’s
Cacilhas, La Batalema
CC-BY: Os textos deste blog podem ser reporduzidos contanto que sejam informados autor e origem.