Uma Breve Introdução ao MongoDB

108
Eduardo Nicola F. Zagari

description

Esta apresentação faz uma rápida introdução ao uso de uma base de dados orientada a documentos, mostrando o mapeamento SQL para Mongo, o Driver Ruby para MongoDB e um ODM para Mongo, o Mongoid.

Transcript of Uma Breve Introdução ao MongoDB

Page 1: Uma Breve Introdução ao MongoDB

Eduardo Nicola F. Zagari

Page 2: Uma Breve Introdução ao MongoDB

Sumário

MongoDB Característica Instalação Mapeamento SQL MongoDB Conexão com Banco via shell Schema Dinâmico Inserção de dados Interando sobre a coleção Sintaxe

Page 3: Uma Breve Introdução ao MongoDB

Sumário

MongoDB Ruby Driver Instalação Conexão com banco Listagem de bases e coleções Criação/acesso de coleções Inserção de documentos Atualização de documentos Busca Índices

Page 4: Uma Breve Introdução ao MongoDB

Sumário

Mongoid Instalação Documentos Persistência Querying Relations

Page 5: Uma Breve Introdução ao MongoDB

Características

Armazenamento Orientado a Documentos

Suporte full-index Replicação e Alta disponibilidade Auto sharding Querying Atualizações rápidas in-place Map/Reduce GridFS

Page 6: Uma Breve Introdução ao MongoDB

Instalando MongoDB

Download

Crie o diretório de dados

$ curl http://downloads.mongodb.org/osx/mongodb-osx-i386-x.y.z.tgz > mongo.tgz$ tar xzf mongo.tgz

$ sudo mkdir –p /data/db$ sudo chmod 777 /data/db

Page 7: Uma Breve Introdução ao MongoDB

Instalação MongoDB

Inicie o servidor e se conecte a eleEm uma shell

Em outra shell

$ ./mongodb-XXXXXXX/bin/mongod

$ ./mongodb-XXXXXXX/bin/mongodb.foo.save( { a : 1 } ){ "_id" : ObjectId("4e46f2141373c8f77f7ee954"), "a" : 1 }

Page 8: Uma Breve Introdução ao MongoDB

Mapeamento SQL MongoDB

Page 9: Uma Breve Introdução ao MongoDB

Conexão com Banco via shell

Inicie a shell do MongoDB

Para trocar de base, tecle

$ /Applications/mongodb-osx-x86_64-1.8.2/bin/mongoMongoDB shell version: 1.8.2connecting to: test

> use mydbswitched to db mydb> show dbsadmin (empty)local (empty)test0.203125GB

Page 10: Uma Breve Introdução ao MongoDB

Schema Dinâmico (Schema Free) MongoDB possui databases, collections

e índices Collections contêm documentos BSON Documentos BSON possuem campos

Sem pré-definição Sem schemas Não há a noção de “ALTER table” Na prática, é comum uma coleção possuir

estrutura de documentos homogênea, no entanto, isto não é um requisito

Page 11: Uma Breve Introdução ao MongoDB

Inserção de Dados

> j = { name : "mongo" };{"name" : "mongo"}> t = { x : 3 };{ "x" : 3 }> db.things.save(j);> db.things.save(t);> db.things.find();{ "_id" : ObjectId("4e47fae21373c8f77f7ee955"), "name" : "mongo" }{ "_id" : ObjectId("4e47faeb1373c8f77f7ee956"), "x" : 3 }

Sem pré-definição do collection

Lazy initialization Docs com camps distintos Atribuição do campo “_id

Page 12: Uma Breve Introdução ao MongoDB

Inserção de mais dados

> for (var i = 1; i <= 20; i++) db.things.save({x : 4, j : i});> db.things.find() { "_id" : ObjectId("4e47fae21373c8f77f7ee955"), "name" : "mongo" }{ "_id" : ObjectId("4e47faeb1373c8f77f7ee956"), "x" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee957"), "x" : 4, "j" : 1 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee958"), "x" : 4, "j" : 2 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee959"), "x" : 4, "j" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "x" : 4, "j" : 4 }…{ "_id" : ObjectId("4e47fcb41373c8f77f7ee963"), "x" : 4, "j" : 13 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee964"), "x" : 4, "j" : 14 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee965"), "x" : 4, "j" : 15 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee966"), "x" : 4, "j" : 16 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee967"), "x" : 4, "j" : 17 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee968"), "x" : 4, "j" : 18 }has more

Page 13: Uma Breve Introdução ao MongoDB

O Comando “it” (iterador)

…{ "_id" : ObjectId("4e47fcb41373c8f77f7ee967"), "x" : 4, "j" : 17 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee968"), "x" : 4, "j" : 18 }has more> it{ "_id" : ObjectId("4e47fcb41373c8f77f7ee969"), "x" : 4, "j" : 19 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee96a"), "x" : 4, "j" : 20 }

Page 14: Uma Breve Introdução ao MongoDB

Acessando dados a partir de uma Query (objeto “cursor”)

> var cur = db.things.find()> while (cur.hasNext()) printjson(cur.next());{ "_id" : ObjectId("4e47fae21373c8f77f7ee955"), "name" : "mongo" }{ "_id" : ObjectId("4e47faeb1373c8f77f7ee956"), "x" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee957"), "x" : 4, "j" : 1 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee958"), "x" : 4, "j" : 2 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee959"), "x" : 4, "j" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "x" : 4, "j" : 4 }…{ "_id" : ObjectId("4e47fcb41373c8f77f7ee965"), "x" : 4, "j" : 15 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee966"), "x" : 4, "j" : 16 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee967"), "x" : 4, "j" : 17 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee968"), "x" : 4, "j" : 18 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee969"), "x" : 4, "j" : 19 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee96a"), "x" : 4, "j" : 20 }

Page 15: Uma Breve Introdução ao MongoDB

forEach() ao invés de while()

> db.things.find().forEach(printjson); { "_id" : ObjectId("4e47fae21373c8f77f7ee955"), "name" : "mongo" }{ "_id" : ObjectId("4e47faeb1373c8f77f7ee956"), "x" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee957"), "x" : 4, "j" : 1 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee958"), "x" : 4, "j" : 2 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee959"), "x" : 4, "j" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "x" : 4, "j" : 4 }…{ "_id" : ObjectId("4e47fcb41373c8f77f7ee965"), "x" : 4, "j" : 15 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee966"), "x" : 4, "j" : 16 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee967"), "x" : 4, "j" : 17 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee968"), "x" : 4, "j" : 18 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee969"), "x" : 4, "j" : 19 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee96a"), "x" : 4, "j" : 20 }

Page 16: Uma Breve Introdução ao MongoDB

Tratando cursor no estilo array

Nota: documentos até o mais alto acessado(quinto documento, no nosso caso) são todos carregados em RAM ao mesmo tempo Não apropriado para grandes coleções

> var cur = db.things.find();> printjson(cur[4]); { "_id" : ObjectId("4e47fcb41373c8f77f7ee959"), "x" : 4, "j" : 3 }

Page 17: Uma Breve Introdução ao MongoDB

Convertendo cursor em array

Nota: cursores não são fotografias “instantâneas”

Operações feitas na coleção por usuários distintos concorrentemente podem ou não serem retornadas pelo cursor

Deve-se usar bloqueios para consultas instantâneas

> var arr = db.things.find().toArray();> arr[5];{ "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "x" : 4, "j" : 4 }

Page 18: Uma Breve Introdução ao MongoDB

Especificando retorno de Queries Query documents:

{a:A, b:B, …} significa “WHERE a==A AND b=BB AND …”

> db.things.find({name:"mongo"}).forEach(printjson);{ "_id" : ObjectId("4e47fae21373c8f77f7ee955"), "name" : "mongo" }

Page 19: Uma Breve Introdução ao MongoDB

Especificando retorno de Queries

> db.things.find({x:4}).forEach(printjson);{ "_id" : ObjectId("4e47fcb41373c8f77f7ee957"), "x" : 4, "j" : 1 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee958"), "x" : 4, "j" : 2 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee959"), "x" : 4, "j" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "x" : 4, "j" : 4 }…{ "_id" : ObjectId("4e47fcb41373c8f77f7ee965"), "x" : 4, "j" : 15 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee966"), "x" : 4, "j" : 16 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee967"), "x" : 4, "j" : 17 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee968"), "x" : 4, "j" : 18 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee969"), "x" : 4, "j" : 19 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee96a"), "x" : 4, "j" : 20 }

Page 20: Uma Breve Introdução ao MongoDB

Especificando retorno de Queries

> db.things.find({x:4}, {j:true}).forEach(printjson);{ "_id" : ObjectId("4e47fcb41373c8f77f7ee957"), "j" : 1 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee958"), "j" : 2 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee959"), "j" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "j" : 4 }…{ "_id" : ObjectId("4e47fcb41373c8f77f7ee965"), "j" : 15 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee966"), "j" : 16 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee967"), "j" : 17 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee968"), "j" : 18 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee969"), "j" : 19 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee96a"), "j" : 20 }

Partial Documents

Page 21: Uma Breve Introdução ao MongoDB

findOne( ) – Syntactic Sugar

Documentos podem ser obtidos invocando-se next() sobre um cursor Tratando o cursor como um array Convertendo cursor em array etc findOne() : Açúcar Sintático

> printjson(db.things.findOne({j:4})); { "_id" : ObjectId("4e47fcb41373c8f77f7ee95a"), "x" : 4, "j" : 4 }

Page 22: Uma Breve Introdução ao MongoDB

limit( ): limitando o retorno

> db.things.find().limit(3);{ "_id" : ObjectId("4e47fae21373c8f77f7ee955"), "name" : "mongo" }{ "_id" : ObjectId("4e47faeb1373c8f77f7ee956"), "x" : 3 }{ "_id" : ObjectId("4e47fcb41373c8f77f7ee957"), "x" : 4, "j" : 1 }

Page 23: Uma Breve Introdução ao MongoDB

Sintaxe

Page 24: Uma Breve Introdução ao MongoDB

Sintaxe

Page 25: Uma Breve Introdução ao MongoDB

Sintaxe

Page 26: Uma Breve Introdução ao MongoDB

Sintaxe

Page 27: Uma Breve Introdução ao MongoDB

Sintaxe

Page 28: Uma Breve Introdução ao MongoDB

MongoDB Ruby Driver

Escrito em Ruby Com uma extensão em C para

velocidade Otimizado à simplicidade Pode ser usado sozinho, além servir

de base para várias bibliotecas de mapeamento de objetos

Page 29: Uma Breve Introdução ao MongoDB

Instalação

Para garantir a última versão do rubygems

Para instalar a gem do mongo

Para otimização de performance, instala-se também a gem bson_ext

$ gem update --system

$ gem install mongo

$ gem install bson_ext

Page 30: Uma Breve Introdução ao MongoDB

Iniciando…

Usando a gem

Criando uma conexão

require 'rubygems' # not necessary for Ruby 1.9require 'mongo'

db = Mongo::Connection.new.db("mydb")db = Mongo::Connection.new("localhost").db("mydb")db = Mongo::Connection.new("localhost", 27017).db("mydb”)

Page 31: Uma Breve Introdução ao MongoDB

Iniciando…

Listando todas as bases

Removendo uma base

connection = Mongo::Connection.new # (optional host/port args)connection.database_names.each { |name| puts name }connection.database_info.each { |info| puts info.inspect}

connection.drop_database('database_name’)

Page 32: Uma Breve Introdução ao MongoDB

Iniciando

Listagem de coleções

Acessando uma coleção

Que é um alias para o método [ ]

db.collection_names.each { |name| puts name }

coll = db.collection("topicos")

coll = db[”topicos"]

Page 33: Uma Breve Introdução ao MongoDB

Inserção de documentos

doc = {"name" => "MongoDB", "type" => "database", "count" => 1, "faculdade" => "FECOMP", "info" => {"x" => 203, "y" => 102} }coll.insert(doc)

{ "name" : "MongoDB", "type" : "database", "faculdade" : "Fecomp" "count" : 1, "info" : { x : 203, y : 102 } }

Page 34: Uma Breve Introdução ao MongoDB

Atualização de documentos

Reescrevendo o documento

Usando um operador atômico para mudar um valor único

asaa

coll.update({"_id" => doc[:_id]}, {"$set" => {"name" => "MongoDB Ruby"}})

doc["name"] = "MongoDB Ruby"coll.update({"_id" => doc[:_id]}, doc)

Page 35: Uma Breve Introdução ao MongoDB

Busca

Encontrando o primeiro documento

asaa

=> {"_id"=>BSON::ObjectId('4e78d41bed686f02d1000001'), "name"=>"MongoDB", "faculdade" : "Fecomp”, "info"=>{"x"=>203, "y"=>102}, "count"=>1, "type"=>"database”}

my_doc = coll.find_one()puts my_doc.inspect

Page 36: Uma Breve Introdução ao MongoDB

Adicionando mais documentos

Contando documentos

100.times { |i| coll.insert("i" => i) }

{ "i" : value}

puts coll.count()

Page 37: Uma Breve Introdução ao MongoDB

Busca

Usando um Cursor para obter todos os documentos

asaa

coll.find().each { |row| puts row.inspect }

Page 38: Uma Breve Introdução ao MongoDB

Busca com Queries

Obtendo um único documento com queries

Obtendo um conjunto de documentos

asaa

coll.find("i" => 71).each { |row| puts row.inspect }

coll.find("i" => {"$gt" => 50}).each { |row| puts row.inspect }coll.find("i" => {"$gt" => 20, "$lte" => 30}).each { |row| puts row.inspect }

Page 39: Uma Breve Introdução ao MongoDB

Busca com Queries

Queries com Expressões Regulares

Dinamicamente

asaa

coll.find("name" => /^M/).each { |row| puts row.inspect }

search_string = params['search']

#Constructor Syntaxcoll.find({"name" => Regexp.new(search_string)})

# Literal syntaxcoll.find({"name" => /#{search_string}/})

Page 40: Uma Breve Introdução ao MongoDB

Índices

Criando índices

Explicit ”descending"

asaa

coll.create_index("i")

coll.create_index([["i", Mongo::DESCENDING]])

Page 41: Uma Breve Introdução ao MongoDB

Índices

Criando índice geo-espacial

Query com limites

Obtendo a lista de índices de uma coleção

people.create_index([["loc", Mongo::GEO2D]])

people.find({"loc" => {"$near" => [50, 50]}}, {:limit => 20}).each do |p| puts p.inspect end

coll.index_information()

Page 42: Uma Breve Introdução ao MongoDB

Mongoid

Object-Document-Mapper (ODM) para MongoDB

Escrito em Ruby Provém uma API familiar aos

desenvolvedores Ruby acostumados com Active Record, enquanto alavanca o poder da ausência de schema do MongoDB

Page 43: Uma Breve Introdução ao MongoDB

Instalação

Para instalar a gem do mongoid

Arquivo de configuração mongoid.yml

Por programação

$ gem install mongoid

host: localhostdatabase: mydb

Mongoid.load!("path/to/your/mongoid.yml")

Mongoid.configure do |config| config.master = Mongo::Connection.new.db(”mydb")end

Page 44: Uma Breve Introdução ao MongoDB

Documentos

Objetos devem incluir Mongoid::Document a fim de serem persistidos

Armazenamentoclass Person include Mongoid::Documentend

class Person include Mongoid::Document store_in :citizensend

Page 45: Uma Breve Introdução ao MongoDB

Campos

Outros tipos: Array, BigDecimal, Boolean, Date, DateTime, Float, Hash, Integer, Range, Symbol e Time

class Person include Mongoid::Document store_in :citizens field :first_name, type: String field :middle_name, type: String field :last_name, type: Stringend

Page 46: Uma Breve Introdução ao MongoDB

Campos: get e set

Obtém o valor do campo first_name

Atribui o valor para o campo first_name

person.first_nameperson[:first_name]person.read_attribute(:first_name)

person.first_name = ”José"person[:first_name] = ”José"person.write_attribute(:first_name, ”José")

Page 47: Uma Breve Introdução ao MongoDB

Campos: get e set para vários campos Obtém os valores dos campos em

um hash

Atribui os valores de campos em um documento

person.attributes

Person.new(first_name: "Jean-Baptiste", middle_name: "Emmanuel")person.attributes = { first_name: "Jean-Baptiste", middle_name: "Emmanuel" }person.write_attributes( first_name: "Jean-Baptiste", middle_name: "Emmanuel")

Page 48: Uma Breve Introdução ao MongoDB

Defaults

class Person include Mongoid::Document field :blood_alcohol_level, type: Float, default: 0.40 field :last_drink, type: Time, default: -> { 10.minutes.ago }end

Page 49: Uma Breve Introdução ao MongoDB

Serialização de Campos customizados

class Profile include Mongoid::Document field :location, type: Pointend

class Point include Mongoid::Fields::Serializable

def deserialize(object) [ object["x"], object["y"] ] end

def serialize(object) { "x" => object[0], "y" => object[1] } endend

Page 50: Uma Breve Introdução ao MongoDB

Campos Dinâmicos

Suporte a Campos dinâmicos Permite get, set e persistência de

atributos mesmo que um campo não tenha sido definido para ele

Não usar getters e setters Usar os métodos acessores:

person[:gender]person.read_attribute(:gender)

person[:gender] = "Male"person.write_attribute(:gender, "Male")

Page 51: Uma Breve Introdução ao MongoDB

Acesso: Protected

class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_protected :passwordend

# Ajusta atributos em uma pessoa de forma apropriadaPerson.new(first_name: "Corbin")person.attributes = { first_name: "Corbin" }person.write_attributes(first_name: "Corbin")

# Tenta ajudar os valores, levantando um erroPerson.new(first_name: "Corbin", password: "password")person.attributes = { first_name: "Corbin", password: "password" }person.write_attributes(first_name: "Corbin", password: "password")

Page 52: Uma Breve Introdução ao MongoDB

Acesso: Accessible

class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_accessible :first_nameend

# Ajusta atributos em uma pessoa de forma apropriadaPerson.new(first_name: "Corbin")person.attributes = { first_name: "Corbin" }person.write_attributes(first_name: "Corbin")

# Tenta ajudar os valores, levantando um erroPerson.new(first_name: "Corbin", password: "password")person.attributes = { first_name: "Corbin", password: "password" }person.write_attributes(first_name: "Corbin", password: "password")

Page 53: Uma Breve Introdução ao MongoDB

Acesso: Overriding

Person.new(first_name: "Corbin") do |person| person.password = "password"end

Page 54: Uma Breve Introdução ao MongoDB

Dirty Tracking

person = Person.firstperson.name = "Alan Garner”

# Checa para ver se o documento foi alteradoperson.changed? #=> true# Obtém um array dos nomes dos campos alteradosperson.changed #=> [ :name ]# Obtém um hash do antigo e do novo valor para cada campoperson.changes #=> { "name" => [ "Alan Parsons", "Alan Garner" ] }# Checa se um campo específico foi alteradoperson.name_changed? #=> true# Obtém as mudanças para um campo específicoperson.name_change #=> [ "Alan Parsons", "Alan Garner" ]# Obtém o valor anterior de um campoperson.name_was #=> "Alan Parsons"

class Person include Mongoid::Document field :name, type: Stringend

Page 55: Uma Breve Introdução ao MongoDB

Limpando mudanças

person = Person.firstperson.name = "Alan Garner"

# Reinicializa o nome alterado de volta ao originalperson.reset_name!person.name #=> "Alan Parsons"

Page 56: Uma Breve Introdução ao MongoDB

Vendo as mudanças anterioresperson = Person.firstperson.name = "Alan Garner"person.save #=> Clears out current changes.

# Vê mudanças anterioresperson.previous_changes #=> { "name" => [ "Alan Parsons", "Alan Garner" ] }

Page 57: Uma Breve Introdução ao MongoDB

Persistência

Model.create Model.create! Model#save Model#save! Model#update_attributes Model#update_attributes! Model#update_attribute Model#delete Model#destroy Model.delete_all Model.destroy_all

Page 58: Uma Breve Introdução ao MongoDB

Model.create

# Insere um novo poeta na base.Person.create(first_name: "Heinrich", last_name: "Heine")

# Isto também pode ser feito usando um blocoPerson.create(first_name: "Heinrich") do |doc| doc.last_name = "Heine"end

collections[”citizens"].insert({ "_id" : ..., "first_name" : "Heinrich", "last_name" : "Heine” })

Page 59: Uma Breve Introdução ao MongoDB

Model.create!

# Insere um novo poeta na base, levantando um erro # se a validação falhar.Person.create!(first_name: "Heinrich", last_name: "Heine")

# Isto também pode ser feito usando um blocoPerson.create!(first_name: "Heinrich") do |doc| doc.last_name = "Heine"end

collections[”citizens"].insert({ "_id" : ..., "first_name" : "Heinrich", "last_name" : "Heine” })

Page 60: Uma Breve Introdução ao MongoDB

Model#save

# Insere um novo poeta na base.person = Person.new(first_name: "Heinrich", last_name: "Heine")person.save

# Grava sem executar as validaçõesperson.save(validate: false)

# Grava os campos modificados de um documento existenteperson.first_name = "Christian Johan"person.save

# Comando de inserção de um novo documentocollections[”sitizens"].insert({ "_id" : ..., "first_name" : "Heinrich", "last_name" : "Heine” })

# Comando de atualização do doc modificadocollections["people"].update({ { "_id" : ... }, { "$set" : { "first_name" : "Christian Johan” } } })

Page 61: Uma Breve Introdução ao MongoDB

Model#save!

# Insere um novo poeta na base.person = Person.new(first_name: "Heinrich", last_name: "Heine")person.save!

# Grava os campos modificados de um documento existenteperson.first_name = "Christian Johan"person.save!

# Comando de inserção de um novo documentocollections[”sitizens"].insert({ "_id" : ..., "first_name" : "Heinrich", "last_name" : "Heine” })

# Comando de atualização do doc modificadocollections["people"].update({ { "_id" : ... }, { "$set" : { "first_name" : "Christian Johan” } } })

Page 62: Uma Breve Introdução ao MongoDB

Model#update_attributes

# Update the provided attributes.person.update_attributes(first_name: "Jean", last_name: "Zorg")

# Comando de atualização do doc modificadocollections[”citizens"].update({ "_id" : ..., "first_name" : ”Jean", "last_name" : ”Zorg” })

Page 63: Uma Breve Introdução ao MongoDB

Model#update_attributes!

# Update the provided attributes.person.update_attributes!(first_name: "Jean", last_name: "Zorg")

# Comando de atualização do doc modificadocollections[”citizens"].update({ "_id" : ..., "first_name" : ”Jean", "last_name" : ”Zorg” })

Page 64: Uma Breve Introdução ao MongoDB

Model#update_attribute

# Update the provided attributes.person.update_attribute(first_name: "Jean")

# Comando de atualização do doc modificadocollections[”citizens"].update({ "_id" : ..., "first_name" : ”Jean” })

Page 65: Uma Breve Introdução ao MongoDB

Model#delete

person.delete

collections[”citizens"].remove("_id" : ... )

Page 66: Uma Breve Introdução ao MongoDB

Model#destroy

person.destroy

collections[”citizens"].remove("_id" : ... )

Page 67: Uma Breve Introdução ao MongoDB

Model#delete_all

# Apaga todos os documentos da coleçãoPerson.delete_all

# Apaga todos os documentos da coleção que satisfaçam a condiçãoPerson.delete_all(conditions: { first_name: "Heinrich" })

# Comando para apagar todoscollections[”citizens"].remove

# Comando para apagar docs que satisfaçam condiçãocollections[”citizens"].remove("first_name" : "Heinrich")

Page 68: Uma Breve Introdução ao MongoDB

Model#destroy_all

# Apaga todos os documentos da coleçãoPerson.destroy_all

# Apaga todos os documentos da coleção que satisfaçam a condiçãoPerson.destroy_all(conditions: { first_name: "Heinrich" })

# Comando para apagar todoscollections[”citizens"].remove

# Comando para apagar docs que satisfaçam condiçãocollections[”citizens"].remove("first_name" : "Heinrich")

Page 69: Uma Breve Introdução ao MongoDB

Atomicidade na Persistênicia

Embora Mongoid realize operações atômicas por trás da cena por default, há casos em que se deseja fazê-lo explicitamente sem persistir outros campos Model#add_to_set Model#inc Model#pull_all Model#push

Page 70: Uma Breve Introdução ao MongoDB

Model#add_to_set

person.add_to_set(:aliases, "Bond")

collections[”citizens"].update( { "_id" : ... }, { "$addToSet" : { "aliases" : "Bond" } })

Page 71: Uma Breve Introdução ao MongoDB

Model#inc

person.inc(:age, 1)

collections[”citizens"].update( { "_id" : ... }, { "$inc" : { "age" : 1 } })

Page 72: Uma Breve Introdução ao MongoDB

Model#pull_all

person.pull_all(:aliases, [ "Bond", "James" ])

collections[”citizens"].update( { "_id" : ... }, { "$pullAll" : { "aliases" : [ "Bond", "James" ] } })

Page 73: Uma Breve Introdução ao MongoDB

Model#push

person.push(:aliases, "007")

collections[”citizens"].update( { "_id" : ... }, { "$push" : { "aliases" : "007" } })

Page 74: Uma Breve Introdução ao MongoDB

Querying

Mongoid queries são em Criteria, um wrapper de queries dinâmicas do MongoDB, que é encadeável e de avaliação “tardia”, por só acessar a base quando necessário.

Page 75: Uma Breve Introdução ao MongoDB

Criteria – métodos de query

Model.all_in Model.also_in Criteria#and Model.any_in Model.any_of Model.asc Model.desc Criteria#distinct Model.excludes

Model.includes Model.limit Model.near Model.not_in Model.only Model.order_by Model.skip Model.where Model.without

Page 76: Uma Breve Introdução ao MongoDB

Model.all_in | Criteria#all_in

# Traz todas as pessoas que tem Bond e 007 como aliasesPerson.all_in(aliases: [ "Bond", "007" ])

{ "aliases" : { "$all" : [ "Bond", "007" ] }}

Page 77: Uma Breve Introdução ao MongoDB

Model.also_in | Criteria#also_in

# Traz pessoas com aliases igual a Bond ou 007Person.also_in(aliases: [ "Bond", "007" ])Person.any_in(aliases: [ "Bond" ]).also_in(aliases: [ "007" ])

{ "aliases" : { "$in" : [ "Bond", "007" ] }}

Page 78: Uma Breve Introdução ao MongoDB

Criteria#and

# Traz todas as pessoas com last_name Jordan e first_name iniciando com dPerson.where(last_name: "Jordan").and(first_name: /^d/i)

{ "last_name" : "Jordan", "first_name" : /^d/i }

Page 79: Uma Breve Introdução ao MongoDB

Model.any_in | Criteria#any_in

# Traz todas as pessoas com Bond e/ou 007 como aliasesPerson.any_in(aliases: [ "Bond", "007" ])Person. any_in(aliases: [ "Bond", "007", "James" ]). any_in(aliases: [ "Bond", "007" ])

{ "aliases" : { "$in" : [ "Bond", "007" ] }}

Page 80: Uma Breve Introdução ao MongoDB

Model.any_of | Criteria#any_of

# Traz todas as pessoas com last_name Penn ou TellerPerson.any_of({ last_name: "Penn" }, { last_name: "Teller" })

{ "last_name" : { "$or" : [ { "last_name" : "Penn" }, { "last_name" : "Teller" } ] }}

Page 81: Uma Breve Introdução ao MongoDB

Model.asc | Criteria#asc

# Retorna pessoas ordenadas por first_name e last_name em ordem alfabética crescentePerson.asc(:first_name, :last_name)Person.ascending(:first_name, :last_name)

{ "sort" : {[ [ "first_name", Mongo::ASCENDING ], [ "last_name", Mongo::ASCENDING ] ]} }

Page 82: Uma Breve Introdução ao MongoDB

Model.where | Criteria#where

# Traz todas as pessocas com first_name EmmanuelPerson.where(first_name: "Emmanuel")

# Traz todas as pessoas com first_name Emmanuel usando Javascript.Person.where("this.first_name == 'Emmanuel'")

# Traz todas as pessoas de Berlin, onde address é “embutido”Person.where("addresses.city" => "Berlin")

{ "first_name" : "Emmanuel" }

{ "$where" : "this.first_name == 'Emmanuel'" }

{ "addresses.city" : "Berlin" }

Page 83: Uma Breve Introdução ao MongoDB

Model.where | Criteria#where

# Exemplo de queries usando símbolo h4s para realizar critérios mais complexosPerson.where(:title.all => ["Sir"])Person.where(:age.exists => true)Person.where(:age.gt => 18)Person.where(:age.gte => 18)Person.where(:title.in => ["Sir", "Madam"])Person.where(:age.lt => 55)Person.where(:age.lte => 55)Person.where(:title.ne => "Mr")Person.where(:title.nin => ["Esquire"])Person.where(:aliases.size => 2)Person.where(:location.near => [ 22.50, -21.33 ])Person.where(:location.within => { "$center" => [ [ 50, -40 ], 1 ] })

Page 84: Uma Breve Introdução ao MongoDB

Criteria + Modificação

Pode-se usar Mongoid criteria para se criar um seletor e usá-lo para se modificar documentos no banco

Page 85: Uma Breve Introdução ao MongoDB

Criação

# Cria uma pessoa com title Sir e first_name Lancelot e a persistePerson.where(title: "Sir", first_name: "Lancelot").createPerson.where(title: "Sir").create(first_name: "Lancelot")

# Constrói uma pessoa com title Sir e first_name Lancelot, sem salvá-laPerson.where(title: "Sir", first_name: "Lancelot").buildPerson.where(title: "Sir").build(first_name: "Lancelot")

Page 86: Uma Breve Introdução ao MongoDB

Atualização

# Atualiza todas as pessoas que têm last_name Oldman com um novo first_namePerson.where(last_name: "Oldman").update_all( first_name: "Pappa Gary")

Page 87: Uma Breve Introdução ao MongoDB

Remoção

# Apaga todos os cavaleiros de Sir Arthur da basePerson.where(title: "Sir").and(king: "Arthur").delete_allPerson.where(title: "Sir", king: "Arthur").destroy_all

Page 88: Uma Breve Introdução ao MongoDB

Finders

Métodos Finders não são encadeáveis Retornam arrays de documentos ou um

documento único (com exceções) Métodos:

Model.all Model.count Model.exists? Model.find Model.find_or_create_by Model.find_or_initialize_by Model.first Model.last

Page 89: Uma Breve Introdução ao MongoDB

Model.all

# Encontra todas as pessoas pelas condições e opções compatíveis com MongoDBPerson.allPerson.all(conditions: { first_name: /^dur/i, "addresses.city" => "Berlin" })Person.all(conditions: { title: "Sir" }, limit: 5)Person.all(sort: [[ :first_name, :asc ]])

Page 90: Uma Breve Introdução ao MongoDB

Model.count

# Obtém o montante de documentos que satisfazem a(s) condição(ões)Person.countPerson.count(conditions: { title: "Sir" })

Page 91: Uma Breve Introdução ao MongoDB

Model.exists?

# Existe algum documento na base que satisfaça a(s) condição(ões)?Person.exists?Person.exists?(conditions: { title: "Sir" })

Page 92: Uma Breve Introdução ao MongoDB

Model.find | Criteria#find

#Permite encontrar um vários documentos pelo idPerson.find(id)Person.find("4baa56f1230048567300485c")Person.where(last_name: "Black").find(id)

Person.find([id_one, id_two])Person.find(["4baa56f1230048567300485c","4baa56f1230048567300485d"])Person.where(last_name: "Black").find([ id_one, id_two ])

Page 93: Uma Breve Introdução ao MongoDB

Model.find_or_create_by

# Encontra um documento que satisfaça a condição ou cria um novo, se não houver nada persistidoPerson.find_or_create_by(first_name: "Syd", last_name: "Vicious")

Page 94: Uma Breve Introdução ao MongoDB

Model.find_or_initialize_by

# Encontra um documento que satisfaça a condição ou inicializa um novo, se não houver nada persistidoPerson.find_or_initialize_by(first_name: "Syd", last_name: "Vicious")

Page 95: Uma Breve Introdução ao MongoDB

Model.first

# Encontra o primeiro documento da base que satisfaça a condição. Retorna um documento ou nil, se nada for encontrado. Pode-se definir a ordenação, a fim de se ditar qual documento deve ser retornado. Person.first(conditions: { first_name: "Syd" })Person.first(sort: [[ :first_name, :asc ]])

Page 96: Uma Breve Introdução ao MongoDB

Model.last

# Encontra o último documento da base que satisfaça a condição. Retorna um documento ou nil, se nada for encontrado. Pode-se definir a ordenação, a fim de se ditar qual documento deve ser retornado. Person.last(conditions: { first_name: "Syd" })Person.last(sort: [[ :first_name, :asc ]])

Page 97: Uma Breve Introdução ao MongoDB

Escopos

Mongoid permite definir escopos dentro dos modelos, a fim de se filtrar resultados de busca

São definidos no nível da Classe São encadeáveis

Page 98: Uma Breve Introdução ao MongoDB

Named Scopes

class Person include Mongoid::Document field :occupation, type: String field :age, type: Integer

scope :rock_n_rolla, where(occupation: "Rockstar") scope :washed_up, where(:age.gt => 30) scope :over, ->(limit) { where(:age.gt => limit) }end

# Encontra todos os roqueirosPerson.rock_n_rolla

# Econtra os roqueiros que já deviam ter paradoPerson.washed_up.rock_n_rolla

# Encontra o TremendãoPerson.rock_n_rolla.over(60)

scope :current, where(:start_date.lte => Date.today)scope :current, -> { where(:start_date.lte => Date.today) }

Page 99: Uma Breve Introdução ao MongoDB

Métodos de Classe

# Encontra todos os roqueirosPerson.rock_n_rolla

# Econtra os roqueiros que já deviam ter paradoPerson.washed_up.rock_n_rolla

# Encontra o TremendãoPerson.rock_n_rolla.over(60)

class Person include Mongoid::Document field :occupation, type: String field :age, type: Integer

class << self def rock_n_rolla where(occupation: "Rockstar") end def washed_up where(:age.gt => 30) end def over(limit) where(:age.gt => limit) end endend

Page 100: Uma Breve Introdução ao MongoDB

Métodos de Classe e Named Scopes

Person.rock_n_rollaPerson.washed_up.rock_n_rollaPerson.rock_n_rolla.over(60)

class Person include Mongoid::Document field :occupation, type: String field :age, type: Integer

scope :washed_up, where(:age.gt => 30) scope :over, ->(limit) { where(:age.gt => limit) }

class self.rock_n_rolla where(occupation: "Rockstar") endend

Page 101: Uma Breve Introdução ao MongoDB

Default Scopes

# Econtra os roqueiros que já deviam ter paradoPerson.washed_up

# Se quiser encontrar os mais velhos que não são roqueirosPerson.unscoped.washed_up

class Person include Mongoid::Document field :occupation, type: String field :age, type: Integer

default_scope where(occupation: "Rockstar") scope :washed_up, where(:age.gt => 30) end

Page 102: Uma Breve Introdução ao MongoDB

Relacionamentos

Associações entre modelos no domínio e no banco.

Podem ser “embutidas” ou “referenciadas

Embedded: 1…N: “embeds_many” e “embedded_in” 1…1: “embeds_one” e “embedded_in”

Referenced: 1…N: “has_many” e “belongs_to” 1…1: “has_one” e “belongs_to” N…N: “has_and_belongs_to_many” e

“has_and_belongs_to_many”

Page 103: Uma Breve Introdução ao MongoDB

Callbacks

after_initialize before_validation after_validation before_create around_create after_create before_update

around_update after_update before_save around_save after_save before_destroy around_destroy after_destroy

Page 104: Uma Breve Introdução ao MongoDB

Callbacks

class Article include Mongoid::Document field :name, type: String

set_callback(:save, :before) do |document| document.generate_slug end

protected def generate_slug self.slug = name.to_permalink endend

class Article include Mongoid::Document field :name, type: String field :body, type: String field :slug, type: String

before_create :generate_slug

protected def generate_slug self.slug = name.to_permalink endend

Page 105: Uma Breve Introdução ao MongoDB

Observers

Implementa o comportamento fora da classe

Instanciação

class ArticleObserver < Mongoid::Observer def after_save(article) Notifications.article("[email protected]", "New article", article).deliver endend

require 'article_observer'require 'audit_observer'Mongoid.observers = ArticleObserver, AuditObserverMongoid.instantiate_observers

config.mongoid.observers = :article_observer, :audit_observer

Config/application.rb

Page 106: Uma Breve Introdução ao MongoDB

Mapeamento

class AuditObserver < Mongoid::Observer observe :account, :balance

def after_update(record) AuditTrail.new(record, "UPDATED") endend

Page 107: Uma Breve Introdução ao MongoDB

Validations

validates_acceptance_of validates_associated validates_confirmation_of validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_uniqueness_of

Page 108: Uma Breve Introdução ao MongoDB

Fontes

MongoDB: Features, Quickstart and Tutorial(http://www.mongdb.com)

MongoDB Ruby Driver Tutorial (http://api.mongodb.org/ruby/current/file.TUTORIAL.html)

Mongoid (http://mongoid.org/)