NoSQL, MongoDB y MongoMapper

Post on 20-Jun-2015

2.041 views 1 download

description

Presentación del Campus Party Bogota 2010

Transcript of NoSQL, MongoDB y MongoMapper

NoSQL: MongoDB y MongoMapper

Patrick Aljord, David y Jorge Cuadrado

Tokyo Cabinet

BigTable

Características

Esquema libreDistribuidas y escalablesCapacidad de manejo de grandes volúmenes de datosPerformance/rendimiento

Tipos de NoSQL

Key/Value (Llave/valor)

Column-oriented (orientadas a columnas)

Document-oriented (orientadas a documentos)

Key/Value

¿Qué es?una llaveun blob

Ventajas:muy simple para implementarmuy rapido

Útil para:el cache(memcache)sistema de manejo de cola (redis)

limitado para aplicaciones complejas

Column-oriented

¿Qué es?utiliza tablas dinamicasmas flexible que tablas de RDBMSmulti-dimensional

Ventajas:el sistema de consulta se acerca al de un RDBMSdiseño de google, soporta grandes cargasversiones

Útil para:grandes colecciones

mapping de los datos a objetos no es natural (igual que rdbms)

Document-oriented¿Qué es?

formato json o xmlmuy flexible

Ventajas:mapea facilmente a un objeto (python, ruby, c++ etc)

Útil para:aplicaciones web complejastodo tipo de aplicacion que utiliza documentos y necesita flexibilidad

La soluciones que aporta el NoSQL

built-in replication, master a masterMap/Reducemas simple de instalar (se necesita tomar un curso para instalar a oracle o sqlserver)casi todas son software libre, muy accesible para todoshecho para programadores, mas orientadas a la programaciones (map/reduce lo entienden mejor los programadores que los administradores de base de datos)

¿Qué es el map/reduce?

Permite procesar los datos guardados en un cluster de computadores de forma paralela.Sus resultados son similares a los de una función de agregación como GROUP BY en SQL.

¿Que es el map?

El map es aplicar una función sobre cada elemento de un arreglo y retornar un arreglo con sus elementos modificados.

Ejemplo (en ruby): > matriz = [1,2] > matriz.map { |n| n+2 } => [3, 4]

¿Qué es el reduce?

Reduce es aplicar una función sobre cada elemento de un arreglo y retornar un solo elemento. Se hace iterando sobre cada elemento del arreglo. Cada iteracion empieza con el valor retornado por la iteracion anterior y hace algo con esta. Por esta razón, un reduce se debe iniciar con una valor de entrada.

ejemplo (en ruby), con valor de entrada igual a cero: > [1, 2, 3].reduce(0) do |sum, value| sum + value end => 6

Las ventajas del map/reduce

Esta hecho para poderse ejecutar en paralelo => Fácil de dividir en varias tareas

Todos los datos se pueden agrupar.Probado y comprobado por los grande(google, amazon, facebook).

(credit: amazon)

SQL-RDBMS Key/Value

Variedad de consultas Rendimiento

Las principales funcionalidades

Document-oriented storageConsultasModificadores atómicosMap/ReduceGridFS: Almacenamiento de archivosSoporte para Full IndexReplicación & Alta DisponibilidadAuto-Sharding

¿Como instalar MongoDB?

1. Para instalar mongodb descargamos el binario correspondiente para nuestro sistema operativo http://www.mongodb.org/display/DOCS/Downloads

2. descomprimes el paquete y creas los directorios /data y /data/db o C:\data y C:\data dependiendo de tu SO

3. para iniciar el servicio corres el binario /bin/mongod o bin\mongod.exe que viene en el paquete que has descargado en el paso 1

para un entorno de producción se debe usar un sistema operativo de 64-bits.

¿Como instalar mongodb?

Para los sistemas unix*(linux,freebsd, OSX) es recomendado usar el sistema de paquetes de cada sistema operativo.

adicionalmente 10gen provee de paquetes oficiales para las distribuciones Linux Debian, Ubuntu, CentOS y Fedora

http://www.mongodb.org/display/DOCS/Ubuntu+and+Debian+packageshttp://www.mongodb.org/display/DOCS/CentOS+and+Fedora+Packages

¿ Cómo se guardan los datos en MongoDB?

Documento: Álbum de un artista

Colección: la música que tiene el almacén

{ nombre: "Yellow Submarine", autor: "The Beatles", canciones: ["Yellow Submarine", "Only A Northern Song", "All Together Now", "Hey Bulldog", "It's All Too Much", "All You Need Is Love", "Pepperland", "Sea Of Time", "Sea Of Holes", "Sea Of Monsters", "March Of The Meanies", "Pepperland Laid Waste", "Yellow Submarine In Pepperland" ], genero: "Rock", anho: 1969, cantidad: 20}

¿BSON?

ObjectID (identificador del documento)Números(Reales y Enteros)ArreglosObjetos(Hash)Binarios(Blobs)Tiempos(UTC)vacio(nil, null)

¿Que tipos de datos se pueden guardar en MongoDB?

http://bsonspec.org/

¿Cómo conectarse a mongoDB?

Drivers Oficiales:CC++JavaJavascriptPerlPHPPythonRuby

Drivers Comunitarios:C# and .NETClojureErlangGoGroovyHaskellnode.jsLuaLuaMongoScalaScheme (PLT)Smalltalk

http://www.mongodb.org/display/DOCS/Drivers

console: ./bin/mongo

Referenciar o EmpotrarAlbum{ _id: "aaa", nombre: "Yellow Submarine", autor: "The Beatles", genero: "Rock", anho: 1969, cantidad: 20}

Cancion{ nombre: "Yellow Submarine", duracion: 159, album_id: "aaa" },{ nombre: "Only A Northern Song", duracion: 204, album_id: "aaa" }{ nombre: "All Together Now", duracion: 130, album_id: "aaa" }{ nombre: "Hey Bulldog", duracion: 191, album_id: "aaa" }{ nombre: "It's All Too Much", duracion: 384, album_id: "aaa"}{ nombre: "All You Need Is Love", duracion: 231, album_id: "aaa"}

Referenciar o Empotrar{ nombre: "Yellow Submarine", autor: "The Beatles", canciones: [ { nombre: "Yellow Submarine", duracion: 159 }, { nombre: "Only A Northern Song", duracion: 204 }, { nombre: "All Together Now", duracion: 130 }, { nombre: "Hey Bulldog", duracion: 191 }, { nombre: "It's All Too Much", duracion: 384 }, { nombre: "All You Need Is Love", duracion: 231 }, ...], genero: "Rock", anho: 1969, cantidad: 20}

¿Cómo añadir y eliminar documentos a una colección?

./mongo> use tienda_de_musica> album = { nombre: "Let it be", autor: "The Beatles", canciones: [], genero: "Rock", anho: 1970, cantidad: 10 }> db.musica.save(album);> db.musica.find();{ "_id" : ObjectId("4c10a976eaa67158a0d74b4b"), "nombre": "Let it be", "autor" : "The Beatles", "canciones" : [ ], "genero" : "Rock", "anho" : 1970, "cantidad" : 10 }

>db.musica.remove({});>db.musica.remove({autor: "The Beatles"})

¿Como actualizar un documento? Modificadoresdb.coleccion.update( criterio_de_busqueda, objeto_o_operadores, [upsert?], [múltiple?])

>db.musica.update( {_id: ObjectId("4c10a976eaa67158a0d74b4b")}, {$inc: { cantidad: -1 }});

>db.musica.update( _id: 10, $set: { cantidad: 0 }, true);

http://www.mongodb.org/display/DOCS/Updating

Un poco más acerca de los modifcadores

$set y $unset: sirven para asignarle y quitarle el valor a un campo de un documento respectivamente.$inc: incrementan el valor asignado a un campo, solo es valido para valores enteros.$push,$pushAll: añaden uno o varios valores a un arreglo de datos contenido en un campo del documento.$addToSet: añade un valor a un arreglo si el valor no esta repetido.$pop, $pull, $pullAll: son operadores para borrar los valores contenidos en un arreglo.

http://www.mongodb.org/display/DOCS/Updating

¿Cómo hacer consultas en MongoDB?Operadores condicionales para describir criterios de búsqueda:$gt(>) $lt(<), $gte(<=), $lte(>=), $ne(!=)>db.things.find({j : {$lt: 3}});$exists chequea que el documento tenga o no un campo> db.things.find( { a : { $exists : true } } );

Operadores solo para arreglos:>db.things.find(a : {$in: x}$in a incluye al menos un valor del arreglo x.$nin negación de $in>db.things.find(a : {$all: x}$all a incluye todos los valores de x

http://www.mongodb.org/display/DOCS/Advanced+Queries

¿Cómo hacer consultas en MongoDB?WHEREsql> select * from musica where cantidad=1;> db.musica.find({cantidad: 1});sql> select nombre from musica where cantidad<2;> db.musica.find({cantidad: {$lt: 2}}, {'nombre': 1});sql>select * from musica where name like 'The%';>db.musica.find( { name : /^The/ } );

ORDER BYsql> select * from musica ORDER BY anho desc;> db.musica.find({}).sort({anho: -1});

LIMIT y OFFSETsql> select * from musica LIMIT 10 OFFSET 5;>db.musica.find().skip(5).limit(10)

¿Cómo hacer consultas en MongoDB?

COUNTsql>SELECT COUNT(*) FROM musica WHERE autor = "The Beatles";>db.musica.count({autor: "The Beatles"})

DISTINCTsql> select distinct autor from musica;>db.musica.distinct("autor")

¿Cómo hacer consultas en MongoDB?

GROUP BYsql>select autor, count(*) from musica where genero="rock" group by autor

db.musica.group({key: { autor: true }, cond: { genero: "Rock" }, reduce: function(obj, prev) { prev.csum += obj.cantidad; }, initial: { csum: 0 }});

¿Como usar map/reduce en MongoDB?

// MapReduce esta hecho para hacer operaciones de agregaciones.// Tomamos documentos de la coleccion Comentario:

{ text: "jajaja! buena presentacion!", author: 'eliot', votes: 2 }// Aqui tenemos un documento Comentario con un autor, el texto y la cantidad de votos.

¿Como usar map/reduce en MongoDB?

// Queremos calcular la cantidad de votos para cada autor de todos los comentarios que han hecho.var map = function() { emit(this.author, {votes: this.votes}); };

// Esto devuelve una colleccion de pares de llave valor como: [ {"eliot", {votes: 2}}, {"eliot", {votes: 5}}, {"dwight", {votes: 3}} ]

¿Como usar map/reduce en MongoDB?

// A la funcion reduce, se manda cada llave unica y una matriz conteniendo todos los valores para esta llave, // por ejemplo para la llave "eliot", reduce recibe:reduce("eliot", [{votes: 2}, {votes: 5}]);

// Teniendo eso, es fácil para cada autor obtener la suma de todos los votos que han obtenido en todos sus comentarios:var reduce = function(key, values) { var sum = 0; values.forEach(function(doc) { sum += doc.votes; }); return {votes: sum};};

¿Como usar map/reduce en MongoDB?

// Se ejecuta así:var op = db.comments.mapReduce(map, reduce);

// Para obtener los resultados:db[op.result].find(); [{ "_id" : "eliot", "value" : { "votes" : 7 } }, { "_id" : "kbanker", "value" : { "votes" : 3 } }]

¿GridFS?

Almacenamiento de archivos de todo tamaño sin comprometer su stack.

Viene con binarios y bibliotecas

API simple: list, put, get, delete

Sharding

Auto-Shardingparticionamento de los datos en varios servidorsharding por coleccionproceso mongos (routing)replica set

Sharding

http://www.mongodb.org/display/DOCS/Sharding+Introduction

Información Geo espacial

¿Quienes usan MongoDB?

http://www.mongodb.org/display/DOCS/Production+Deployments

http://mongomapper.com/http://github.com/jnunemaker/mongomapper

¿Como empezar a usar MongoMapper?

Instalar>sudo gem install mongo_mapper

Incluir en el proyecto Railsagregar la la dependencia en config/environment.rbconfig.gem "mongo_mapper", :version => "0.8.2", :source => "http://gemcutter.org"

¿Como empezar a usar MongoMapper?

Configurar la conexión a la base de datosconfig/database.yml

development: database: nombre-del-proyecto-development host: localhost port: 27017test: database: nombre-del-proyecto-testproduction: database: nombre-del-proyecto-production

Incluir en el proyecto Rails

Configurar la conexión a la base de datosconfig/initializers/mongodb.rbMongoMapper.setup(YAML.load_file(Rails.root.join('config', 'database.yml')), Rails.env, { :logger => Rails.logger, :passenger => false })

¿Cómo definir un modelo?

app/model/album.rb

class Album include MongoMapper::Document key :nombre, String key :autor, String key :genero, String key :anho, Integer key :cantidad, Integer key :canciones, Arrayend

¿Comó definir un modelo empotrado?

app/model/cancion.rbclass Cancion include MongoMapper::EmbeddedDocument key :name, String key :duracion, Integerendapp/model/album.rbclass Album include MongoMapper::Document ... has_many :canciones, :class_name => "Cancion"end

¿Que tipo de llaves existen?

los tipos de llaves que estan definidos en MongoMapper son:

ObjectIDStringIntegerBooleanArrayHashTimeBinarySet

¿Se pueden definir nuevo tipos de llaves?class Point attr_reader :x, :y

def self.to_mongo(value)...end def self.from_mongo(value)...end

def initialize(*args)...endend

¿Cómo se definen las relaciones uno a muchos?

class Album ... has_many :canciones ...end

class Cancion ... key :album_id, ObjectID belongs_to :album ...end

¿Cómo se definen las relaciones uno a uno?

class Cancion ... has_one :video ...end

class Video ... key :cancion_id, ObjectID belongs_to :cancion ...end

¿Cómo se definen las relaciones muchos a muchos?

class Cancion ... key :album_ids, Array many :albums, :in => :album_ids ...end

class Album ... key :canciones_ids, Array has_many :canciones, :in => :canciones_ids ...end

¿MongoMapper tiene relaciones polimorfas?

class Comment ... key :commentable_id, ObjectId key :commentable_type, String belongs_to :commentable, :polymorphic => trueend

class Album ... has_many :comments, :as => :commentable, :class_name => "Comment"end

¿Cómo añadir validaciones a los modelos?

class Album include MongoMapper::Document key :nombre, String, :unique => true key :autor, String, :required => true key :genero, String, :in => ["Rock", "Pop", "Tropical"] key :anho, Integer key :cantidad, Integer validates_presence_of :nombre, :message => "no ah sido asignado" many :cancionesend

¿Qué validaciones existen en MongoMapper?

required => boolean # necesariaunique => boolean # unicaformat => regexp # con un formatoin => array # incluidanot_in => array # excluidalength => Integer/Range/Hash # tamaño

además puedes usar la api de validatable para agregar mas validaciónesvalidates_presence_of, validates_format_of, validates_true_for,etchttp://validatable.rubyforge.org/

¿Cómo hacer consultas usando MongoMapper?

Modelo.find(id_o_ids)> Album.find("4c10a976eaa67158a0d74b4b")> Album.find(["4c10a976eaa67158a0d74b4b", "4c10a976eaa67158a0d74b4c"])Modelo.first(criterio_opciones)> Album.first({:genero => "Rock"})

Modelo.all(criterio_opciones)>Album.all({:cantidad.lt => 5, :limit => 10, :order => "cantidad asc"})

>Modelo.paginate(criterio_opciones)Album.paginate(:per_page => 10, :page => 2, :genero => "Rock")

¿Cómo usar los modificadores con MongoMapper?

Modelo.<modifcador>(<criterio>, <valores>)modificador: increment, decrement, set, unset, push, push_all, add_to_set, pull, pull_all, pop

>Album.decrement( { :id => "4c10a976eaa67158a0d74b4b"}, { cantidad: 1 });>Album.add_to_set( {id: => "4c10a976eaa67158a0d74b4b"}, canciones: "Foo"});

>Album.collection.update(criteria, modificadores, opciones)>Album.collection.update({:genero => "Rock"}, { "$inc" => {:cantidad => 10}, "$pop" => {"canciones" : 1} }

http://nosql.shapado.com

¿Preguntas?