Introduccion a NoSQL
Los fabricantes de BD Relacionales han presentado habitualmente su producto como la unica solucion para la persistencia de datos.
NoSQL propone que la capa de persistencia no tiene porque ser responsabilidad de un unico sistema, que la mejor herramienta para cada proposito sea utilizada.
NoSQL - Not Only SQL - es una categoria de sistemas de gestion de base de datos alternativa a los basado en el modelo relacional
Tanto los RDBMS como NoSQL son sistemas de almacenamiento estructurado, sin embargo, NoSQL no tiene schemas, no permite operaciones JOIN y es horizontalmente escalable
La diferencia principal es la forma en la que se almacenan los datos.
En una RDBMS hay que convertir nuestros datos a tablas, para despues se transformados en objetos usando un lenguaje de programacion.
En NoSQL simplemente se guardan los datos, sin necesidad de definir esquemas o estructura por adelantado.
Caracteristicas principales
-
Facil de usar en clústers de balanceo de carga convencionales - faciltan escalabilidad horizontal
- Almacenamiento de datos persistentes
- No tienen esquemas fijos
- Suelen tener un lenguaje de consultas propio en lugar de usar un estandar
- Tienen propiedades ACID (Atomicity, Consistency, Isolation, Durability) en cada nodo del cluster.
ACID / BASE
En el mundo relacional estamos familiarizados con las transacciones ACID. Las BBDD NoSQL son mas optimistan y siguen el modelo BASE:
- BAsic availability: El almacén funciona la mayoria del tiempo, incluso ante fallos, gracias al almacenamiento distribuido
- Soft-state: Los almacenes y sus replicas no tienen porque ser consistentes en todo momento. El programador puede verificar su consistencia.
- Eventual consistency: La consistencia se da eventualmente
RDBMS / NoSQL
- Datos a escala web
- Alta frecuencia de lecturas y escrituras
- Cambios frecuentes en el modelos de datos
- No se requiere el mismo nivel de ACID
¿Cuando usar NoSQL?
- La BBDD no escala al trafico existente a un coste aceptable
- El tamaño del esquema de datos ha crecido desproporcionadamente
- El sistema genera muchos datos temporales que no corresponden al almacen principal. (configuración de usuario, carritos de compra, etc)
- Los datos tienen gran cantidad de texto, imágenes y/o columnas como BLOBs
- El modelo de datos puede variar o no requiere una estructura rigida
Arquitectura de las BBDD NoSQL
Existen diferentes tipos de BBDD NoSQL de acuerdo a su implementacion.
BBDD Clave / Valor
- Gestion de tamaño
- Cargas de escrituras masivas orientadas al stream
- Alta disponibilidad
- MapReduce
BBDD orientadas a Documentos
- Modelado de datos natural
- Amigables al programador
- Desarrollo rapido
- Orientadas a la web: CRUD
BBDD orientadas a Grafos
- Modelar un dominio en forma de grafo
- Buen rendimiento cuando los datos están interconectados y no son tabulares
- Operaciones transaccionales que exploten relaciones entre entidades
Teorema CAP
- Consistencia: Todos los nodos ven los mismos datos al mismo tiempo
- Disponibilidad: Cada peticion recibe una respuesta acerca de si tuvo exito o no
- Tolerancia a la particion: El sistema continua funcionando a pesar de la perdida de mensajes
MongoDB
MongoDB es un sistema de base de datos NoSQL orientado a documentos.
MongoDB guarda datos en documentos tipo BSON (Binary JSON) con un esquema dinamico, haciendo la integracion de datos en ciertas aplicaciones mas facil y rapida.
Mongo tiene ciertas limitaciones:
- No hay tablas en la BBDD
- No hay operaciones JOIN
- No hay transacciones complejas
"MongoDB es una base de datos orientada a documentos, escalable, de codigo abierto y de alto rendimiento."
-10gen
Caracteristicas Principales
- Modelo de datos basado en documentos
- Consultas ad hoc
- Índices secundarios
- Replicación
- Velocidad y durabilidad
- Escalabilidad
-
Consultas ad hoc: MongoDB soporta busqueda por campos, consultas de rangos y expresiones regulares. Las consultas pueden devolver un campo especifico o puede ser una funcion JavaScript definida por el usuario.
-
Indexación: Cualquier campo de los documentos puede ser indexado. El concepto de indice es similar al de las BD relacionales.
-
Replicación: MongoDB soporta la replicacion maestro-esclavo.
- El maestro puede ejecutar comandos de lectura y escritura
- El esclavo puede copiar los datos del maestro que solo puede usar para lectura, pero no puede realizar escrituras.
- Balanceo de carga: Mongo escala de forma horizontal usando el concepto de shard.
- El desarrollador elige una llave shard, que determina como serán distribuidos los datos en una colección. Los datos se dividen en rangos y se distribuyen a través de múltiples redes
- Un shard es un maestro con uno o mas esclavos
- MongoDB puede ejecutarse en múltiples servidores, balanceando la carga y/o duplicando los datos para mantener el sistema funcionando en caso de fallo de hardware.
- Almacenamiento de archivos: MongoDB puede ser utilizado con un sistema de archivos usando múltiples servidores para el almacenamiento de archivos.
- Agregación: La función MapReduce y el operador aggregate pueden ser utilizados para el procesamiento por lotes de datos y operaciones de agregación. Esto permite a los usuarios obtener el tipo de resultado que se obtiene cuando se utiliza el comando SQL group-by
- JavaScript en el lado servidor: Mongo tiene la capacidad de realizar consultas usando JavaScript, haciendo que estas sean enviadas directamente a la base de datos para ser ejecutadas.
Casos de uso
- Almacenamiento y registro de eventos
- Sistemas de manejo de documentos y contenido
- Comercio Electrónico
- Juegos
- Problemas de alto volumen
- Aplicaciones móviles
- Almacén de datos operaciones de una página Web
- Manejo de contenido
- Proyectos ágiles
- Estadísticas en tiempo real
¿Cuándo usar MongoDB?
Manipulación de datos
Colecciones
Documentos
Conceptos clave
- MongoDB tiene el concepto de base de datos similar al de schema en el mundo relacional. Dentro de un servidor mongo puede haver 0 o más bases de datos
- Una base de datos puede tener una o más colecciones
- Las colecciones están formadas por 0 o más documentos
- Los documentos están compuestos por uno o varios campos
- Los índices en MongoDB funcionan como los de una RDBMS
- Los cursores son utilizados para acceder progresivamente a los datos recuperados en una consulta. Pueden usarse para contar o moverse hacia delante entre los datos
Ejemplo de documento
{ "_id": ObjectId("4efa8d2b7d284dad101e4bc7"), "Last Name": "PELLERIN", "First Name": "Franck", "Age": 29, "Address": { "Street": "1 chemin des Loges", "City": "VERSAILLES" } }
BSON
- int32 - 4 bytes
- int64 - 8 bytes
- double - 8 bytes
Claves de los documentos
Utilidades
- mongo: Un shell interactivo que permite a los desarrolladores ver, insertar, eliminar y actualizar datos en su base de datos. También permite otras funciones como la replicación de información, configuración de shards y ejecución de JavaScript.
- mongostat: Es una herramienta de línea de comandos que muestra en resumen una lista de estadística de una instancia de MongoDB en ejecución.
- mongotop: Provee un metodo para dar seguimiento a la cantidad de tiempo que dura una lectura o escritura de datos en una instancia.
- mongoimport/mongoexport: Facilita la importación / exportación de contenido desde JSON, CSV o TSV.
Documentacion
Instalación
apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" | tee -a /ect/apt/sources.list.d/10gen.list
apt-get -y update
apt-get -y install mongodb-10gen
service mongodb start
O podemos instalar la version 2.4.9 con
apt-get install mongodb
El siguiente enlace tiene instrucciones para la instalacion en diferentes plataformas:
http://docs.mongodb.org/manual/installation/
Usando MongoDB
> j = { name : "mongo" }; { "name" : "mongo" } > t = { x : 3 }; { "x" : 3 } > db.things.save(j); > db.things.save(t); > db.things.find(); { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d90"), "name" : "mongo" } { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d91"), "x" : 3 } > for (var i = 1; i <= 20; i++) db.things.save({x : 4, j : i}); > db.things.find(); { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d90"), "name" : "mongo" } { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d91"), "x" : 3 } ... Type "it" for more > // Iterate through the remaining items > it { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8da4"), "x" : 4, "j" : 19 } { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8da5"), "x" : 4, "j" : 20 }
> // Store the cursor of the DB in a variable > var cursor = db.things.find(); > while (cursor.hasNext()) printjson(cursor.next()); { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d90"), "name" : "mongo" } { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d91"), "x" : 3 } ... > // Use functional features of JavaScript > db.things.find().forEach(printjson); { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d90"), "name" : "mongo" } { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d91"), "x" : 3 } ... > // cursors like an array > var cursor = db.things.find(); > printjson(cursor[4]); { "_id" : ObjectId("51e50d3b70f9b7c7fdbd8d94"), "x" : 4, "j" : 3 } >
Mongo Shell
- Autocompletado
- Navegar la historia de comandos
- Ofrece un objeto implícito llamado db que representa la base de datos
- Las colecciones se crean automaticamente al insertar el primer documento
- El shell no distingue entre enteros y números de coma flotante, todo se representa como una coma flotante de 64 bits
Comandos
- help - muestra la ayuda
- db.help() - Muestra ayuda de los metodos de la BBDD
- db.<collection>.help() - Detalles de metodos aplicables a una coleccion
- show dbs - Imprime una lista de bases de datos del servidor
- use <database> - Cambia la base de datos, haciendo que db apunte a la BD seleccionada
- show collections - Muestra todas las colecciones de la BD actual
- show users - Imprime los usuarios de la BD
Documentos de consulta
Selectores de consulta
El operador $exists se usa para comprobar la presencia o ausencia de un campo.
db.things.find({ name: { $exists: true } });
Para usar el operador booleano OR, habra que usar el operador $or y asociarle un array de tuplas clave/valor sobre los que realizar el OR.
db.things.find({gender: "m", $or: [{name: "me"}, {name: "Other"}] });
Los arrays en MongoDB son objetos de primera categoria. Por ello, se puede comprobar la inclusión de un elemento dentro de un array al igual que con un único valor.
{knows: "me"} encontrara cualquier documento donde el array knows tenga un valor "me"
Actualizar documentos
Ademas de $set se pueden usar otros modificadores
El modificador $inc se usa para incrementar el campo por una cantidad positiva o negativa
db.things.update({name: "me"}, {$inc: {age: -1}});
Tambien se pueden añadir valores nuevos a campos mediante el modificador $push.
db.things.update({name: "me"}, {$push: {knows: "someone"}});
Podemos escoger crear un documento si no existe. Para esto se coloca un tercer parámetro true en la llamada a update.
db.things.update({name: "me"}, {$inc: {age: -1}}, true);
Si queremos que update actualize todos los documentos que cumplen la expresión hay que poner un cuarto parámetro a true.
db.things.update({name: "me"}, {$inc: {age: -1}}, false, true);
Búsquedas Avanzadas
- Proyecciones: El comando find puede tomar un segundo parametro para seleccionar los campos a mostrar. Por defecto, _id se muestra a menos que se explicite al contrario.
- db.things.find(null, {name: 1, _id: 0});
- Ordenación: El metodo sort() functiona como el selector de las proyecciones. Hay que indicar los campos por los que ordenar, indicando orden ascendente con 1 y descendente con -1.
- db.things.find().sort({name: 1});
- Paginación: Se soporta con los métodos de cursor skip y limit.
- db.things.find().limit(2).skip(1);
- Conteo: Se puede contabilizar resultados
- db.things.count();
Scripting en MongoDB con JavaScript
- Para asignar un valor a la variabe db hay que utilizar el metodo getDB() o el metodo connect().
- conn = new Mongo(); db = conn.getDB("myDatabase");
- db = connect("localhost:27020/myDatabase")
- Dentro del script se invoca a db.getLastError() para esperar a la conclusion de la operacion write.
- No se pueden usar comando de ayuda (show dbs, etc) dentro de un fichero JavaScript.
Para evaluar codigo desde la linea de comando:
mongo test --eval "printjson(db.getCollectionNames())"
Para ejecutar un fichero JS
mongo localhost:27017/test myjsfile.js
Para ejecutar un fichero desde el shell
load("myjsfile.js");
Mas documentacion en:
http://docs.mongodb.org/manual/tutorial/write-scripts-for-the-mongo-shell/
Herramientas graficas
- UMongo es una aplicación de sobremesa multiplataforma para navegar un cluster de MongoDB
-
Se puede acceder a una interfaz administrativa desde http://localhost:28017/
- Existen diferentes alternativas que pueden ser encontradas en http://docs.mongodb.org/ecosystem/tools/administration-interfaces/
Modelado de Datos en MongoDB
- ¿Tiene sentido o es posible colocar los datos en una colección?
- ¿Es posible que se excedan los 16MB de limite para documentos?
- ¿Que datos pertenecen a un documento?
- ¿Se pueden cambiar los datos en un sitio central en lugar de cambiar el conjunto de documentos que contienen esos datos?
- ¿Se van a empotrar documentos o no?
Cuando se crea una aplicación que usa RDBMS se para un tiempo considerable diseñando las tablas y las relaciones entre ellas.
En MongoDB hablamos de diseño de datos dirigido por la aplicacion dado que el concepto de modelado de información es equivalente al modelado basado en objetos de OOP.
Tareas en el nivel de aplicación
La principal diferencia con una RDBMS es la carencia de JOINs.
Esto se debe a que las JOIN no suelen ser escalables. Debido a esto, las JOIN se mueven al nivel de aplicación. Esto significa que si normalizamos los datos hay que hacer una segunda consulta por cada elemento a agregar.
Ejemplo:
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d730"),
name: 'Leto'})
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d731"),
name: 'Duncan', manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d732"),
name: 'Moneo', manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.find({manager: ObjectId("4d85c7039ab0fd70a117d730")})
Relaciones
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"),
name: 'Siona',
manager: [ObjectId("4d85c7039ab0fd70a117d730"),
ObjectId("4d85c7039ab0fd70a117d732")] });
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name:
'Ghanima',
family: {mother: 'Chani', father: 'Paul', brother:
ObjectId("4d85c7039ab0fd70a117d730")} });
Una tecnica alternativa es des-normalizar, replicar datos a traves de varias colecciones.
Esto se ha hecho históricamente en RDBMS por temas de rendimiento, sin embargo, introduce la complicación de tener que contrastar las restricciones de datos a nivel de aplicación.
Relaciones 1 a 1
-
Frecuencia de acceso a documentos
-
Tamaño de los elementos (limitacion de 16MB)
-
La atomicidad y consistencia de los datos
Relaciones 1 a N
Relaciones N a M
Operaciones en MongoDB
CRUD en MongoDB
find() y findOne()
Estos metodos utilizan un documento como primer parametro y un segundo para indicar los campos sobre los que realizar la seleccion.
db.ships.findOne({'name':'USS Defiant'}, {'class':true,'_id':false})
El metodo find devuelve todos los documentos que encuentre y el metodo findOne devuelve solo el primero.
find tiene un limite de 20 resultados, para acceder a los siguientes hay que usar it en el shell.
db.ships.find({class:{$gte:'P'}}, {'name':true, '_id':false})
update()
remove() y drop()
Índices
Se pueden crear indices compuestos
db.unicorns.ensureIndex({name: 1, vampires: -1});
Y asegurar que un indice sea único
db.unicorns.ensureIndex({name: 1}, {unique: true});
Para saber si se esta usando un indice se usa explain
db.unicorns.find().explain()
Si la salida indica que se ha usado un cursos BasicCursor quiere decir que el campo no es indexado, se escanearan mas documentos y tardaran mas las búsquedas y ordenaciones.
{
"cursor" : "BasicCursor", // el campo no es indexado
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 12,
"nscanned" : 12,
"nscannedObjectsAllPlans" : 12,
"nscannedAllPlans" : 12,
"scanAndOrder" : false,
"indexOnly" : false, // si la consulta se puede resolver mirando sólo el índice
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0, // indica cuánto tardó la consulta
"indexBounds" : {
},
"server" : "obssidianPC:27017"
Si se usa un indice el campo cursos tendra asociado un indice del tipo BtreeCursor.
{
"cursor" : "BtreeCursor name_1", // los campos de consulta son indexados
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"name" : [
[
"Pilot",
"Pilot"
]
]
},
"server" : "obssidianPC:27017"
}
La coleccion db.system.indexes contiene detalles de todos los índices de una BD de Mongo.
db.system.indexes.find()
Escritura Asíncrona
Colecciones restingidas
Transacciones
- Tolerar un poco de inconsistencia
- Estructurar la aplicación de modo que quepa en un solo documento, y usar atomicidad a nivel de documento ($inc, $set, etc.)
- Programar las transacciones a nivel de aplicacion
MapReduce en MongoDB
- Se puede paralelizar
- En mongo se puede escribir codigo JavaScript para hacer el procesamiento
- Map: Mapear los datos transformando los documentos de entrada en pares clave/valor
- Reduce: Reducir las entradas conformadas por estos pares para producir el resultado final.
Ejemplo de MapReduce
var map = function() { var key = {resource: this.resource, year: this.date.getFullYear(), month: this.date.getMonth(), day: this.date.getDate()}; emit(key, {count: 1}); }; var reduce = function(key, values) { var sum = 0; values.forEach(function(value) { sum += value['count']; }); return {count: sum}; }; db.hits.mapReduce(map, reduce, {out: {inline:1}})
Pipeline de Agregación
-
$project - Cambia el conjunto de documentos modificando claves y valores
-
$match - Operación de filtrado para reducir el conjunto de documentos
- $group - Reduce el numero de documentos agrupando en base a claves o datos indexados
- $sort - Ordenacion ascendente o descendente
- $skip - Permite saltar documento, es decir, avanzar hasta el documento numero X. Se suele usar juanto a $limit
- $limit - Limita el numero de documentos a procesar
- $unwind - Desagrega los elementos de un array en un conjunto de documentos. Es la unica que incrementa el numero de documentos.
Replicacion y Sharding
La replicación funciona de forma similar a la replicación de una BD relacional.
Mediante la replicacion Master-Slave las escrituras son enviadas a un unico servidor, el maestro, que sincroniza su estado a uno o varios esclavos.
Mongo se puede configurar para soportar lecturas en esclavos o no.
Si el maestro se cae, un esclavo es promocionado como máster automáticamente.
El propósito de la replicación es mejorar la robustez, para mejorar el rendimiento se puede combinar con sharding.
Replica Set
Existen 4 tipos de nodos para configurar un Replica Set.
- Regular: Puede votar y puede convertirse en maestro, el mas comun.
- Arbiter: Puede votar pero no puede convertirse en maestro. Se puede usar para asegurar un mínimo numero de nodos en el set.
- Delayed: Puede votar pero no puede convertirse en maestro. Suele usarse como un nodo de recuperación, los datos suelen estar atrasados por un par de horas.
- Hidden: Usados para analíticas en el replica set, no pueden votar ni ser maestros.
Sharding
El modus operandi de sharding consiste en dividir una colección en varios nodos y acceder después a sus contenidos a través de un nodo especial que actúa como router (mongos).
Es necesario que cada colección declare un shard-key. Esta clave se define para uno o varios campos de un documento y se usa para dividir la coleccion en fragmentos que serán distribuidos entre los nodos lo mas equitativamente posible.
La instancia mongos usa esta clave para determinar el fragmento, y por consiguiente el nodo.
Documentacion "Convert a Replica Set to a Replicated Sharded Cluster":
http://docs.mongodb.org/manual/tutorial/convert-replica-set-to-replicated-shard-cluster/
Programando MongoDB
MongoDB tiene soporte variado de lenguajes y librerias cliente. Podemos encontrar una lista de drivers para diversos entornos en el siguiente enlace:
http://docs.mongodb.org/ecosystem/drivers/
Node.js: Server-side JavaScript
Full-Stack JavaScript
Mean.io
- MongoDB es la BD NoSQL lider, ayudando a negocios a ser mas agiles y escalables.
- Express es un framework para el desarrollo de aplicaciones web minimalista y flexible, basado en Node.js.
- AngularJS es un framework para clientes web que permite extender el vocabulario de HTML con nuevas y potentes funciones.
- Node.js es una plataforma con construida sobre el runtime de JavaScript de Chrome para desarrolar facilmente aplicaciones red rapidas y escalables.
MongoDB y Node.js
// Retrieve var MongoClient = require('mongodb').MongoClient; // Connect to the db MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) { if(err) { return console.dir(err); } var collection = db.collection('test'); var docs = [{mykey:1}, {mykey:2}, {mykey:3}]; collection.insert(docs, {w:1}, function(err, result) { collection.find().toArray(function(err, items) {}); var stream = collection.find({mykey:{$ne:2}}).stream(); stream.on("data", function(item) {}); stream.on("end", function() {}); collection.findOne({mykey:1}, function(err, item) {}); }); });
Mongoose
Mongo ofrece un modelo de datos dinámico y ademas transfiere responsabilidades, como la de realizar transacciones complejas a la capa de aplicación.
Debido a esto, nos conviene usar herramientas que nos faciliten la programación cuando usamos MongoDB como base de datos.
Mongoose es una libreria para Node que permite modelar y manejar datos de una aplicación que use MongoDB. Esto reduce los errores que los programadores puedan crear, ademas de acelerar y facilitar el desarrollo de aplicaciones.
Mongoose nos ayuda con la validacion, el modelado y la logica de negocio.
Instalacion:
npm install mongoose
La documentacion oficial de Mongoose se puede encontrar en
Abrir una conexion
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
// BD abierta
});
Modelado de datos
En mongoose todo esta basado en un Schema.
Atributos
var blogSchema = new Schema({
title: String,
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});
Tipos de datos
- String
- Number
- Date
- Buffer
- Boolean
Mixed
Arrays
ObjectId
Operaciones con Mongoose
var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema);
Tank.find(function(err, tanks){
if(err) return err;
console.log(tanks);
});
La operacion de Mongoose populate es lo mas parecido a una JOIN que podemos encontrar para esta BD. Usando esta funcion, el ODM sustituira las referencias a otros documentos (campos ObjectId) por los documentos en si.
Blog.find().populate('author').exec(function(err, blogs){ if(err) return err;
console.log(blogs); });
Extendiendo los esquemas
Validaciones
var Toy = mongoose.model('Toy', toySchema); Toy.schema.path('color').validate(function (value) { return /blue|green|white|red|orange|periwinkle/i.test(value); }, 'Invalid color');
var toy = new Toy({ color: 'grease'});
toy.save(function (err) {
console.log(err.errors.color.message);
});
Virtuals
personSchema.virtual('name.full').get(function () { return this.name.first + ' ' + this.name.last; });
var Person = mongoose.model('Person', personSchema);
var bad = new Person({ name: { first: 'Walter', last: 'White' } });
console.log('%s is insane', bad.name.full); // Walter White is insane
Para modificar los virtual se pueden definit setters para estos atributos.
personSchema.virtual('name.full').set(function (name) {
var split = name.split(' ');
this.name.first = split[0];
this.name.last = split[1];
});
...
mad.name.full = 'Breaking Bad';
console.log(mad.name.first); // Breaking
console.log(mad.name.last);
Middleware
var schema = new Schema(..);
schema.pre('save', true, function (next, done) {
// calling next kicks off the next middleware in parallel
next();
doAsync(done);
});
Casos de uso de middleware
- Validaciones complejas
- Eliminar documentos dependientes
- Valores por defecto asincronos
- Notificaciones
Conclusiones
MongoDB es una buena opción para reemplazas las bases de datos relaciones tradicionales en nuevas aplicaciones, o para optimizar las ya existentes.
Las BBDD NoSQL son una clara alternativa a los RDBMS sobretodo en aplicaciones web y sociales que requieren una alta escalabilidad.
Pero NoSQL no es la panacea.
NoSQL propone usar la herramienta adecuada para tarea, no sustituir RDBMS con NoSQL. La mayoría de datos existentes son muy estructurados y deberían seguir viendo las RDBMS como primera opción.
La capacidad de hacer JOINs y las garantías ACID son muy importantes para muchas aplicaciones.
Cada herramienta es adecuada para un problema.
Aimar Rodríguez Soto
aimar.rodriguez.s@gmail.com
MongoDB
By Aimar Rodriguez
MongoDB
- 2,791