MongoDB: um banco de dados orientado a documento

jmonteiro 2,354 views 61 slides Jan 18, 2011
Slide 1
Slide 1 of 61
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61

About This Presentation

Palestra ministrada no dia 18 de janeiro de 2011 (2011-01-18) na Campus Party Brasil 2010, na área de Desenvolvimento, em São Paulo/SP.


Slide Content

Júlio Monteiro
[email protected]

/ME
Rails Developer, JobScore (http://www.jobscore.com)

/ME
http://julio.monteiro.eti.br

AGENDA
1.Objetivo
2.Histórico
3.Características
4.Relacional versus MongoDB
5.Consultas
6.Map/reduce
7.Operações atômicas
8.Índices
9.Geoposicionamento
10.Por onde continuar?

OBJETIVO
MongoDB busca aproveitar vantagens
de armazenamentos de chave-valor
(que, no geral, são rápidos e escaláveis)
e banco de dados relacionais tradicionais
(que, no geral, oferecem consultas ricas e várias funcionalidades).
(Adaptado do site oficial do MongoDB)

Quando Chuck Norris fala, todos ficam em silêncio. E morrem.

HISTÓRICO
•Produto da 10gen
•Desenvolvimento iniciou em Outubro de 2007
•Primeira versão pública em Fevereiro de 2009
•Atualmente na versão 1.6
•Licenciado sob a GNU AGPL

CARACTERÍSTICAS (1/2)
•Armazenamento orientado a documentos
•Índices
•Consultas ricas (rich queries)
•Atualizações in-place rápidas
•Map/Reduce

CARACTERÍSTICAS (2/2)
•Replicação e Alta Disponibilidade
•Auto-Sharding
•GridFS
•Suporte Comercial (da 10gen)

RELACIONAL VERSUS
MONGODB

TABELA
id nome sobrenome idade
1 Ana Silva 20
2 Maria Carvalho 22
3 João Chaves 21
4 Mário Schimitd 30
... ... ... ...

DOCUMENTO
Id: 1
Nome: Ana
Sobrenome: Silva
Idade: 20
Id: 2
Nome: Maria
Sobrenome: Carvalho
Idade: 22
Id: 3
Nome: João
Sobrenome: Chaves
Idade: 21
Id: 4
Nome: Mário
Sobrenome: Schimitd
Idade: 30

TERMINOLOGIA
Relacional Tradicional
(MySQL, PostgreSQL, etc)
MongoDB
Database
(Banco de dados)
Database
(Banco de dados)
Table
(Tabela)
Collection
(Coleção)
Row
(Linha, registro)
Document
(Documento)
Column
(Coluna)
Attribute
(Atributo)

MODELO ENTIDADE-
RELACIONAMENTO
MYSQLartigos comentarios palavras_chave artigos_palavras_chave

MODELO ENTIDADE
MONGODBartigos comentarios palavras_chave

DOCUMENTO EM
MONGODB
{
"_id" : ObjectID("4c03e856e258c2701930c091"),
"titulo" : "Campus Party Brasil 2011 vêm aí",
"atalho" : "campus-party-brasil-2011-vem-ai",
"texto" : "A Campus Party Brasil 2011 está chegando, e com elas diversas
atrações!",
"publicado" : true,
"criado_em" : "Mon Oct 4 2010 16:00:00 GMT-0300 (BRT)",
"atualizado_em" : "Mon Oct 4 2010 16:00:00 GMT-0300 (BRT)",
"comentarios" : [
{
"autor" : "Julio",
"email" : "[email protected] ",
"conteudo" : "Gostei muito da Campus!",
"criado_em" : "Mon Oct 4 2010 17:00:00 GMT-0300 (BRT)"
}
],
"palavras_chave" : [ "cpbr4", "campus", "party" ]
}

JSON
JavaScript Object Notation

JSON
JavaScript Object Notation
Binary
B

CONSULTAS

COMO BUSCO...
•... por uma palavra inteira?
db.artigos.find({"titulo" : "campus"})
•... por parte de uma palavra?
db.artigos.find({"titulo" : /campus/i})
•... por uma palavra dentro de um array?
db.artigos.find({"palavras_chave" : "campus"})
•... por uma palavra dentro de um embutido?
db.artigos.find({ "comentarios.email" :
"[email protected] " })

COMO ATUALIZO...
... determinado atributo de um registro?
db.artigos.update(
{ "comentarios.email" : " [email protected] " },
{ $set:
{
"comentarios.$.email" : " [email protected]"
}
}
)

$SET ?

$gt
$gte
$lt
$lte
$ne
$in
$nin
$mod
$all
$size
$exists
$type
$elemMatch
$not
$where
OPERADORES

USANDO OPERADORES
•Maior que ($gt):
terceiraIdade = db.pessoas.find({ "age": { $gt:
75 } })
•Incluindo ($in):
interessante = db.artigos.find({ "tags" : { $in :
["mongodb", "interessante"] } })
•Não incluindo ($nin):
todo = db.tarefas.find({ "status" : { $nin : [ "em
execucao", "terminado" ] } })

FUNÇÕES ARBITRÁRIAS
•Usando funções arbitrárias (com $where):
db.artigos.find({ $where : function() {
return this.acessos % 2 == 0
} })
•Usando agrupamento (com $group):
db.artigos.group({
"key" : { "hits" : true },
"initial" : { "count": 0 },
"reduce" : function(obj, prev) {
prev.count++;
}
})

FUNÇÃO DE AGRUPAMENTO
•Dado que possui documentos como...
{
domain: "www.mongodb.org",
invoked_at: {d:"2009-11-03", t:"17:14:05"},
response_time: 0.05,
http_action: "GET /display/DOCS/Aggregation"
}

FUNÇÃO DE AGRUPAMENTO
•Agrupamento:
db.test.group(
{ cond: {"invoked_at.d": {$gte: "2009-11", $lt:
"2009-12"}}
, key: {http_action: true}
, initial: {count: 0, total_time:0}
, reduce: function(doc, out){ out.count++;
out.total_time+=doc.response_time }
, finalize: function(out){ out.avg_time =
out.total_time / out.count }
} )

FUNÇÃO DE AGRUPAMENTO
•Retorno do agrupamento:
[
{
"http_action" : "GET /display/DOCS/
Aggregation",
"count" : 1,
"total_time" : 0.05,
"avg_time" : 0.05
}
]

MAP/REDUCE

2
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1

4
3
7
4

BANCO DE DADOS
db.items.insert({tags: ['dog', 'cat']})
db.items.insert({tags: ['dog']})
db.items.insert({tags: ['dog', 'mouse']})
db.items.insert({tags: ['dog', 'mouse', 'hippo']})
db.items.insert({tags: ['dog', 'mouse', 'hippo']})
db.items.insert({tags: ['dog', 'hippo']})

MAP
var map = function() {
this.tags.forEach(function(t) {
emit(t, {count: 1})
})
}

REDUCE
var reduce = function(key, val) {
var count = 0;
for(var i = 0, len = val.length; i < len; i++) {
count += val[i].count
}
return { count: count };
}

EXECUTANDO
var result = db.items.mapReduce(map, reduce);

RESULTADO
{
"result" : "tmp.mr.mapreduce_1286209644_2",
"timeMillis" : 30,
"counts" : {
"input" : 6,
"emit" : 13,
"output" : 4
},
"ok" : 1,
}

RESULTADO (MESMO!)
db["tmp.mr.mapreduce_1286209644_2"].find()
db[result['result']].find()

MAP/REDUCE
{ "_id" : "cat", "value" : { "count" : 1 } }
{ "_id" : "dog", "value" : { "count" : 6 } }
{ "_id" : "hippo", "value" : { "count" : 3 } }
{ "_id" : "mouse", "value" : { "count" : 3 } }

OPERAÇÕES ATÔMICAS

OPERAÇÕES ATÔMICAS
•Incrementando com $inc
db.artigos.update(
{ _id : new ObjectId("4c041...")},
{ $inc: {"hits": 1} }
)
•Atualizando:
db.posts.update({}, { $set : { "hits" : 0 }})

ÍNDICES

ÍNDICES
•Desempenho lento para escrita, mas muito mais rápida para
leitura
•Para melhores resultados, crie índices por onde você busca
•MongoDB mantém índices em memória

SEM ÍNDICE
db.items.find({tags: "dog"}).explain();
{
"cursor" : "BasicCursor",
"nscanned" : 6,
"nscannedObjects" : 6,
"n" : 6,
"millis" : 10,
"indexBounds" : {

}
}

APLICANDO O ÍNDICE
db.items.ensureIndex({tags: 1})

COM ÍNDICE
db.items.find({tags: "dog"}).explain();
{
"cursor" : "BtreeCursor tags_1",
"nscanned" : 6,
"nscannedObjects" : 6,
"n" : 6,
"millis" : 0,
"indexBounds" : {
"tags" : [
[
"dog",
"dog"
]
]
}
}

GEOPOSICIONAMENTO

GEOPOSICIONAMENTO
•Geoposicionamento, com MongoDB, é estupidamente
simples
•Apenas adicione um índice:
db.lugares.ensureIndex({ localizacao: "2d" })

LUGARES MAIS PERTO
db.lugares.find({
localizacao: { $near : [
21.123456789, -20.123456789
]}
})

20 LUGARES MAIS PERTO
db.lugares.find({
localizacao: { $near : [
21.123456789, -20.123456789
]}
}).limit(20)

EM UMA ÁREA

EM UMA ÁREA
db.lugares.find({
localizacao: { $within: { $box: {
[
[21.123456789, -20.123456789],
[22.123456789, -21.123456789]
]
}}}
})

POR ONDE CONTINUAR?

WWW.MONGODB.ORG

MONGODB
THE DEFINITIVE GUIDE

REFERÊNCIAS

REFERÊNCIAS

OBRIGADO!
Júlio Monteiro
[email protected]