En esta nueva entrega de la serie dedica a las bases de datos NoSQL vamos a ver que es MongoDB como instalarla y como empezar a trabajar con ella. Después del par de posts dedicados a CouchDB, vamos a darle cancha a otra de las bases de datos NoSQL que más repercusión está teniendo ultimamente, MongoDB.
Introducción
El nombre viene del término inglés “humongous” (colosal) y podemos definirla como una BD documental sin esquema, escalable y de alto rendimiento. Asà es como nos la presentan en la entradilla de su página oficial, pero para entendernos la podrÃamos llamar la “MySQL de las bases de datos NoSQL”. Vale, el apelativo tal vez parezca algo gratuito pero en cierto modo tiene sentido al ver que es una BD rapidÃsima, sencilla en la funcionalidad ofrecida y que, como hizo MySQL hace años, se está ganando la atención de mucha gente.
De forma similar CouchDB, esta BD nos permite almacenar documentos sin un schema predefinido, pero ofrece algunas pequeñas diferencias en cuanto a la organización de la información. En MongoDB partimos del concepto de BD que podrÃa ser análogo al que usamos en las BD de toda la vida y además también tenemos “colecciones” que serÃan como las tablas. Pero a diferencia de MySQL o similares, aquà podremos meter documentos con distintos campos dentro de la misma colección, de modo que esta estructura tiene más un sentido de categorizacion de los elementos que contiene sin obligar a que estos tengan los mismos datos. P.ej. en nuestra BD para un blog podrÃamos tener una colección “autores” y otra “posts”…
Es importante destacar que MongoDB ofrece un rendimiento en inserciones mucho mayor que CouchDB (e incluso algo mejor que MySQL). Vamos, que va como una moto… Pero esto es a costa de sacrificar ciertos “detalles” como p.ej las transacciones. Asà que si estáis pensando en implementar un sistema que precise de estas es mas sencillo usar una base de datos relacional que las soporte (p.ej. MySQL con MyISAM no valdrÃa).
Y como resultado colateral la durabilidad no se ve asegurada con un log de transacciones como el que se puede usar en BD relacionales. ¿Y que quiere decir esto?, pues que cuando pete la base de datos podremos repararla pero es posible que perdamos algunas de las ultimas modificaciones (aquellas que han sido realizadas pero todavia no han sido enviadas a disco). Seguro que a alguno os ha entrado el sudor frÃo, pero resulta que si estáis usando MySQL con el backend MyISAM estáis asumiendo un riesgo parecido
Para evitarnos problemas en estos casos los autores de MongoDB nos recomiendan usar algun tipo de replicación en otra maquina, de forma que tengamos una BD que realize las mismas escrituras que la principal. De esta forma tambien ganamos en tener una copia viva de nuestra BD que puede reemplazar a la principal si esta cae. O servir como otra fuente de lectura de datos para aportar mas rendimiento todavÃa. Lo bueno es que la configuración de esta replicación es bastante sencilla.
Primeros pasos
Pero mejor será que la veamos en funcionamiento, de esta forma nos daremos cuenta de lo poco que cuesta empezar a trabajar con MongoDB. Lo primero es bajarse el paquete correspondiente de la sección de descargas (http://www.mongodb.org/display/DOCS/Downloads) de la página web oficial. En este paquete nos viene ya todo compilado y preparado para ejecutar directamente el servidor de base de datos. Vamos a ello.
Lanzamos el ejecutable “bin/mongod” pasandole el parametro dbpath donde le indicamos el directorio donde nos guardará los datos (debe estar creado antes). P.ej:
bin/mongod --dbpath data
Hecho lo cual deberÃamos ver por la salida estándar los mensajes del servidor tal que asÃ:
Sun Mar 7 17:10:35 Mongo DB : starting : pid = 3517 port = 27017 dbpath = data master = 0 slave = 0 64-bit Sun Mar 7 17:10:35 db version v1.3.3, pdfile version 4.5 Sun Mar 7 17:10:35 git version: 853524dc41aa926f4fd1504e6c46186769f51771 Sun Mar 7 17:10:35 sys info: Linux domU-12-31-39-06-79-A1 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41 Sun Mar 7 17:10:35 waiting for connections on port 27017 Sun Mar 7 17:10:35 web admin interface listening on port 28017
Si vemos algún mensaje de error tal vez sea porque el directorio no está creado o no se lo estamos pasando bien (en nuestro ejemplo “data” está justo en el directorio descomprimido de MongoDB aunque tal vez convendrÃa uno más tipico como p.ej. /var/lib/mongodb)
Ahora abrimos otro terminal y lanzamos el shell “bin/mongo” desde el que podremos realizar tareas de mantenimiento y consulta sobre las bases de datos. Veremos algo asÃ:
MongoDB shell version: 1.3.3 url: test connecting to: test type "help" for help
Si tecleamos “help” podemos ver algunos comandos disponibles, pero lo mas sencillo es que vayamos viendo los mas importantes poco a poco.
Una cosa interesante es que el shell esta basado en un motor Javascript (SpiderMonkey ahora, es posible que se use el V8 de Google en un futuro) de forma que podemos ejecutar codigo javascript intercalado con nuestras órdenes.
> a
Sun Mar 7 17:20:38 JS Error: ReferenceError: a is not defined (shell):0
> var a=1;
> a
1
> print('hola')
hola
> for (var i=0; i<5; i++) {print('hola: ' + i)}
hola: 0
hola: 1
hola: 2
hola: 3
hola: 4
Como hemos visto en el mensaje inicial se esta usando la base de datos “test”, si queremos podemos cambiar a otra usando la orden “use”:
> use pruebas switched to db pruebas > show dbs admin local
Si os fijáis al listar las BDs existentes con “show dbs” no nos muestra la “test” ni la “prueba” a la que acabamos de cambiar. Esto es asà porque MongoDB crea las bases de datos (y las colecciones) cuando insertamos algo en ellas. Hasta que lo hagamos no veremos ninguna de estas estructuras.
Trabajando con documentos
Para insertar documentos en nuestra BD usaremos la orden “db.coleccion.insert”:
> db.perros.insert({'nombre':'Lassie', 'raza':'Collie'})
MongoDB soporta varios tipos para sus datos. Tenemos los tipicos del formato JSON (string, integer, boolean, double, null, array, object) asi como varios especiales (date, object id, binary data, regular expression, code).
Teniendo en cuenta esto podrÃamos insertar un registro como este:
> db.perros.insert({'nombre':'Rex', 'nacido':new Date(2005, 01, 23), 'colores':['marron', 'negro']})
Como tenemos un interprete Javascript todo para nosotros podemos hacer como como esta:
> for (var i=0; i<5; i++) {db.perros.insert({'nombre':'Desconocido ' + i})}
Para poder consultar los datos de nuestra BD podemos usar la orden “db.coleccion.find”:
> db.perros.find()
{ "_id" : ObjectId("4b93d6efda357cdeec678511"), "nombre" : "Lassie", "raza" : "Collie" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678513"), "nombre" : "Desconocido 1" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
{ "_id" : ObjectId("4b93dc91da357cdeec678518"), "nombre" : "Rex", "nacido" : "Wed Feb 23 2005 00:00:00 GMT+0100 (CET)", "colores" : [ "marron", "negro" ] }
En caso de que tengamos muchos resultados MongoDB solo muestra los 10 primeros y podemos ir viendo los grupos restantes con la orden “it”.
Aquà es interesante ver como MongoDB nos ha generado un campo “_id” para cada una de los documentos insertados. Este campo id es autogenerado por defecto y está indexado (hace que las busquedas por él sean mucho mas rapidas). Si ya tenemos un código que nos pueda servir como identificador se lo podemos pasar en la inserción y MongoDB lo usará.
> db.perros.insert({'_id':'K9', 'nombre':'Bobby', 'tipo':'perro policia'})
> db.perros.find()
{ "_id" : ObjectId("4b93d6efda357cdeec678511"), "nombre" : "Lassie", "raza" : "Collie" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678513"), "nombre" : "Desconocido 1" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
{ "_id" : ObjectId("4b93dc91da357cdeec678518"), "nombre" : "Rex", "nacido" : "Wed Feb 23 2005 00:00:00 GMT+0100 (CET)", "colores" : [ "marron", "negro" ] }
{ "_id" : "K9", "nombre" : "Bobby", "tipo" : "perro policia" }
> db.perros.insert({'_id':'K9', 'nombre':'Bobbsy', 'tipo':'perro policia'})
E11000 duplicate key error index: pruebas.perros.$_id_ dup key: { : "K9" }
Lo interesante es que a find le podemos pasar un documento de forma que MongoDB nos devolverá aquellos documentos cuyos valores coincidan. Esto es lo que se conoce como “query by example”. P.ej:
> db.perros.find({'nombre':'Lassie'})
{ "_id" : ObjectId("4b93d6efda357cdeec678511"), "nombre" : "Lassie", "raza" : "Collie" }
Un detalle importante es que podemos utilizar el tipo “regular expression” en estas consultas:
> db.perros.find({'nombre':/^Desconocido/})
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678513"), "nombre" : "Desconocido 1" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
Por supuesto podemos pasarle un documento con varios campos al “find” y nos devolveria los documentos para los que coinciden todos ellos.
Además de por campos especificos podemos consultar con unos operadores especiales, entre los que se encuentran:
- $gt: Valores mayores que el que le pasamos.
- $lt: Valores menores que el que le pasamos.
- $gte: Valores mayores o iguales que el que le pasamos.
- $lte: Valores menores o iguales que el que le pasamos.
- $ne: Distinto
- $in: Si el valor esta entre los que le pasamos como array.
Aparte hay más operadores de consulta que podemos ver en la sección de la documentación correspondiente (consultas avanzadas)
Veamos unos ejemplos:
> db.perros.find({'nombre':{'$gt':'Desconocido 1', '$lte':'Desconocido 3'}})
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
> db.perros.find({'nombre':{'$ne':'Desconocido 1'}})
{ "_id" : ObjectId("4b93d6efda357cdeec678511"), "nombre" : "Lassie", "raza" : "Collie" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
{ "_id" : "K9", "nombre" : "Bobby", "tipo" : "perro policia" }
{ "_id" : ObjectId("4b93dc91da357cdeec678518"), "nombre" : "Rex", "nacido" : "Wed Feb 23 2005 00:00:00 GMT+0100 (CET)", "colores" : [ "marron", "negro" ] }
> db.perros.find({'nombre':{'$in':['Lassie', 'Rex']}})
{ "_id" : ObjectId("4b93d6efda357cdeec678511"), "nombre" : "Lassie", "raza" : "Collie" }
{ "_id" : ObjectId("4b93dc91da357cdeec678518"), "nombre" : "Rex", "nacido" : "Wed Feb 23 2005 00:00:00 GMT+0100 (CET)", "colores" : [ "marron", "negro" ] }
Después del “find” podemos usar varias funciones que nos permiten obtener distintos resultados.
P.ej. si queremos saber el numero de resultados obtenidos usamos “count”:
> db.perros.find().count() 8
Con limit y skip podemos obtener un rango de resultados determinado. Limit nos dice cuantos documentos se obtienen y skip se salta los n primeros resultados de la consulta (esto es muy útil para mostrar los resultado paginados):
> db.perros.find({'nombre':/^Desco/})
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678513"), "nombre" : "Desconocido 1" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
> db.perros.find({'nombre':/^Desco/}).limit(2)
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678513"), "nombre" : "Desconocido 1" }
> db.perros.find({'nombre':/^Desco/}).skip(2)
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
> db.perros.find({'nombre':/^Desco/}).skip(3).limit(1)
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
Además del “find” podemos usar la orden “findOne” si sólo necesitamos un resultado:
> db.perros.findOne({'nombre':'Lassie'})
Aparte de estas facilidades de consulta tenemos la opción de utilizar consultas map-reduce (si habéis leido los posts de CouchDB os sonará). Y si necesitamos que las busquedas sobre un campo determinado sean lo más rápidas posibles podemos crear Ãndices con la orden “db.coleccion.ensureIndex”:
> db.perros.ensureIndex({nombre:1});
Si necesitamos modificar un objeto podemos recuperarlo con una consulta, realizar los cambios que deseemos y utilizar el comando “db.coleccion.save”:
> var p = db.perros.findOne({'nombre':'Lassie'})
> p
{
"_id" : ObjectId("4b93d6efda357cdeec678511"),
"nombre" : "Lassie",
"raza" : "Collie"
}
> p["nacido"] = new Date(2001, 02, 12)
"Mon Mar 12 2001 00:00:00 GMT+0100 (CET)"
> db.perros.save(p)
> db.perros.find({'nombre':'Lassie'})
{ "_id" : ObjectId("4b93d6efda357cdeec678511"), "nombre" : "Lassie", "raza" : "Collie", "nacido" : "Mon Mar 12 2001 00:00:00 GMT+0100 (CET)" }
Aquà hay que tener cuidado con un detalle de Javascript: el mes que se le pasa al objeto date va de 0 a 11 (0=Enero, 1=Febrero…).
Como podéis imaginar esta es un forma poco óptima ya que tenemos que realizar 2 accesos: uno para recuperar el objeto y otro para hacer “save” de la modificación. Pero por suerte, MongoDB nos ofrece una orden “db.coleccion.update” que nos permite realizar modificaciones en un sólo paso.
Esta orden tiene todos estos parámetros:
db.collection.update( criterio, obj, upsert, multi )
donde:
- criterio: expresión que nos permite seleccionar los documentos que se actualizarán.
- obj: objeto a modificado o bien expresión con operadores $.
- upsert: true si esto es un “upsert”
- multi: true si queremos modificar todos los resultados de “criterio” (por defecto solo se modifica el primero)
Los operadores $ son parecidos a los vistos en las consultas, pero ahora permiten realizar acciones especÃficas de modificación de datos. Por ejemplo, tenemos $inc que nos permite incrementar el valor del campo, $set si queremos cambiar un valor, $push para introducir un nuevo elemento en un array, etc…
El parámetro “upsert” quiere decir que esta actualizacion creará un nuevo registro en caso de que el “criterio” no devuelva ningún documento.
> db.perros.update({'nombre':'Lassie'}, {'$set':{'hijos':2}})
> db.perros.find({'nombre':'Lassie'})
{ "_id" : ObjectId("4b93ea74da357cdeec678519"), "hijos" : 2, "nacido" : "Mon Mar 12 2001 00:00:00 GMT+0100 (CET)", "nombre" : "Lassie", "raza" : "Collie" }
> db.perros.update({'nombre':'Lassie'}, {'$inc':{'hijos':3}})
> db.perros.find({'nombre':'Lassie'})
{ "_id" : ObjectId("4b93ea74da357cdeec678519"), "hijos" : 5, "nacido" : "Mon Mar 12 2001 00:00:00 GMT+0100 (CET)", "nombre" : "Lassie", "raza" : "Collie" }
> db.perros.update({'nombre':'Lassie'}, {'nombre':'Lassie 2', 'edad':'4'})
> db.perros.find({'nombre':'Lassie'})
> db.perros.find({'nombre':'Lassie 2'})
{ "_id" : ObjectId("4b93ea74da357cdeec678519"), "nombre" : "Lassie 2", "edad" : "4" }
Estas operacion realizadas con los operadores $ tienen la caracterÃstica de ser atómicas lo cual quiere decir que o suceden o no suceden, sin termino medio.
Por último si queremos eliminar registros podemos utilizar la orden “db.coleccion.remove”:
> db.perros.remove({'nombre':'Lassie 2'})
> db.perros.find()
{ "_id" : ObjectId("4b93d6f1da357cdeec678512"), "nombre" : "Desconocido 0" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678513"), "nombre" : "Desconocido 1" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678514"), "nombre" : "Desconocido 2" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678515"), "nombre" : "Desconocido 3" }
{ "_id" : ObjectId("4b93d6f1da357cdeec678516"), "nombre" : "Desconocido 4" }
{ "_id" : "K9", "nombre" : "Bobby", "tipo" : "perro policia" }
{ "_id" : ObjectId("4b93dc91da357cdeec678518"), "nombre" : "Rex", "nacido" : "Wed Feb 23 2005 00:00:00 GMT+0100 (CET)", "colores" : [ "marron", "negro" ] }
No hay joins… ¡socorro!
El hecho de no disponer joins es parte fundamental de la escalabilidad de muchos sistema NoSQL. Por ello la información se guarda de una forma menos normalizada que en una BD relacional y se puede acceder a parte de ella sin necesidad de joins. Esto tiene mucho sentido si pensamos que la información puede estar distribuida en varias máquinas, y si hicieramos join contra los datos que están en otra maquina esto anularÃa en parte el beneficio de rendimiento obtenido. Además si tenemos que mostrar un post con sus comentarios podemos obtenerlo todo leyendo un sólo documento de disco, con los beneficios consiguientes de estar leyendo todos los datos secuencialmente.
Por ejemplo, si tenemos un blog podemos guardar los comentarios dentro de cada post (esto irÃa en una colección llamada “posts”):
{
'autor': 'angel',
'titulo': 'Mi primer post...',
'texto': 'Bla bla bla',
'comentarios': [
{'autor':'Manolo Perez', 'texto':'Que artÃculo más bueno...'},
{'autor':'Jose Rodriguez', 'texto':'No me gusta'}
]
}
Lo bueno es que podemos realizar consultas sobre los datos de estos documentos embebidos de forma que podemos obtener los posts que contengan un comentario hecho por Manolo:
db.blog.find({'comentarios.autor':'Manolo'})
Claro, estamos acostumbrados a partir todo en tablas, pero el hecho de disponer de un tipo array y poder embeber subdocumentos dentro de otros nos permite eliminar algunas de las tablas que crearÃamos en una tÃpica aplicación sobre una BD relacional. De todas formas, lo normal es que haya varias colecciones, asi que nos toca guardarnos un campo que apunte al elemento al que queremos enganchar (normalmente el id).
En nuestro ejemplo de blog podriamos tener otra coleccion ‘autores’, donde guardariamos los autores identificados por su nick (angel en el ejemplo), de forma que podemos cruzar facilmente los datos con la coleccion ‘posts’.
Accediendo desde nuestro código
En los ejemplos mostrados anteriormente hemos estado usando el shell de la BD, pero lo que queremos es acceder a los datos desde nuestro código. Para ello MongoDB nos ofrece drivers para los principales lenguajes de programación, ofreciendo una comunicación lo más eficiente posible a nuestro servidor Mongo.
Por ejemplo, asi serÃa un programa en Python (usando el driver pymongo):
import pymongo
colec = pymongo.Connection().mibd.micoleccion
for i in range(10):
colec.insert({'nombre':'Pepe%d' % i})
for r in colec.find():
print r['nombre']


964 387 506
Muy buen tutorial. La red está plagada de artÃculos de BDs relacionales, y ya hace falta que haya un poco de documentación con ejemplos de NoSQL.
Buena introducción, aunque falta por ejemplo explicar cómo se obtienen objetos de una forma ordenada o limitar el número de resultados de una consulta (indispensables ambos para tu ejemplo del blog).
Gracias por el tutorial!
Gracias a ti por el comment.
Lo de lo limitar el numero de resultados se hace con el “limit” (esto esta en el tutorial) y para la ordenación se puede usar “sort”. Un ejemplo:
db.perros.find().sort({‘nombre’:1})
Y si queremos ordenar por orden descendente:
db.perros.find().sort({‘nombre’:-1})
Buena introduccion.
Tengo una consulta , tenemos una applicacion trabajando en este momento con jbpm , ya que no estamos en produccion , hemos trabajado toalmente con hibernate , si tenemos la idea de ir a una base noSQL.
Unsa de las posibilidades es en el momento de ir a produccion , instalar en un ambiente de amazon EC2 usando MongoDB.
Entonces , tengo un problema , como puedo trabajar con mangoDB y jbpm , ya que jbpm trabaja con hibernate.
Se puede crear un dialect para mongoDB ?
Si alguien se topo con algo asi , le agradeceria su ayuda.
Saludos
Hola Pablo,
A bote pronto no he encontrado nada que recomiende ir por este camino:
http://community.jboss.org/message/530214#530214
Aparte de esto es posible que si usaras EC2 te encontraras con limitaciones si trabajas con las instancias “small”. El problema es que estas son de 32 bits y MongoDB te limita a un máximo de 2.5Gb de datos para este tipo de procesador. Por supuesto esta limitación no se aplica para maquinas de 64 bits, asi que lo más seguro es que tuvieras que trabajar con instancias mas grandes (y caras…)
http://blog.mongodb.org/post/137788967/32-bit-limitations
En tu caso te topas con algunos de los problemas de estas soluciones nuevas, que todavÃa no están tan integradas en herramientas como las BD SQL.
Lo más importante es no perder la visión “ingenieril” del tema… al final no deja de ser una herramienta con la que ganas algunas cosas, pero pierdes otras. Como dicen los anglosajones “there is no silver bullet”
Este link ya lo he puesto en un comentario del post sobre CouchDB, pero merece la pena volverlo a poner:
http://www.slideshare.net/ezmobius/where-do-i-put-this-data-lessql
Hola muy buen intro… Pero como haria para poderle agregar mas comentarios, al key comentario, edl ultimo ejemplo.
Muy buen artÃculo. Me ha dejado con bastantes ganas de probarlo.
Gracias.
Hola Gabriel,
Para añadir nuevos elementos a un array se usa la orden “push”.
Suponiendo que el documento a actualizar este en una coleccion llamada “ejemplo” :
db.ejemplo.update( {‘autor’:'angel’, ‘titulo’:'Mi primer post…’}, {$push: {‘comentarios’: {‘autor’:'Perico’, ‘texto’:'Que bien’}}})
Recuerda que la primera parte del update sirve para seleccionar el documento/s a actualizar y la segunda contiene los datos de la actualizacion.
Men esta muy padre el mini tutorial, facil de entender, ademas de que tiene una secuecia logica. Pero ya se necesita una segunda entrada con ejemplos de conectividad con lenguajes como Java o groovy de springs, digo se me ocurre…
por otro lado el NoSQL que escoji es MongoDB, pero en tu opinion cual es el mejor. Se que se tiene que adaptar y mis necesidades y demas cosas tecnicas que se tiene que contemplar pero me interesa saber cuales son las ventajas del que consideres mejor.
Gracias por todo
Pues lo de mejor es relativo, como todo, cada solución nosql se adapta a unas necesidades. Personalmente y por lo que he jugado con MongoDB y CouchDB, la primera me causó mejor impresión. Sobre todo el tema de velocidad de inserción y en la facilidad para consultas ad-hoc, ahà MongoDB gana por goleada.
De todas formas esto no son soluciones mágicas, cada herramienta vale para los suyo. Si lo que necesitas es almacenar datos que no sean excesivamente relacionales, sin transacciones que afecten a varias tablas y en los que te precises guardar datos con esquemas variables (o directamente sin esquema), MongoDB se adaptará muy bien.
En la documentación puedes echarle un vistazo a: http://www.mongodb.org/display/DOCS/Use+Cases
yo tengo una pregunta. estoy tratando de asimilar esto que es totalmente nuevo, en relacion a todo lo de base de datos que se. pero tengo una pregunta:
en el modelo entidad relacion de la mayoria de bases de datos existen tablas que se relacionan unas con otras muchas veces para no repetir informacion.
ejemplo:
una tabla “trabajdor” se relaciona con una tabla “profesion”. entonces muchos trabajadores pueden tener una misma profesion. esto hace que no tengamos que escribir la msima profesion para cada trabajador sino, solo lo relacionamos..
pero en mongodb, no se como se crearia ese vinculo, si se puede o de que forma es que funciona. agradeceria una explciacion, y espero haber sido claro en mi pregunta. muchas gracias.
Depende, hay dos soluciones posibles: embeber o enlazar.
- Embeber: Introduces los datos dentro del documento “padre”, en ciertos casos se puede hacer sin introducir replicaciones.
Por ejemplo, para modelar un post de un blog puedes hacer algo asÃ, embebiendo los comentarios dentro del post:
{
"titulo": "Primer post",
"autor": "admin",
"text": "Hola, blah blah blah..."
"comentarios": [
{
"autor": "pepe",
"texto": "Buen Post!"
},
{
"autor": "manuel",
"texto": "No está mal"
}
]
}
Esto permite ahorrarte el tener que crear una tabla (colección en MongoDB) para guardar los comentarios. Además de que puedes recuperar el post y todos sus comentarios de una tacada, sin necesidad de cruzar varias tablas.
- Enlazar: Relacionas un documento de una tabla con el id de otro. Para ellos se puede usar datos “normales” como puede ser el “autor” del ejemplo del blog que he puesto arriba. PodrÃamos tener una colección de usuarios a los que accedemos por estos logins (admin, pepe, manuel…).
Otra opción para enlazar es usar DBRef, que es algo parecido pero incluyendo el nombre de la colección contra la que enganchas. Estas tienen la ventaja de que las APIs para varios lenguajes soportados por MongoDB te recuperan automáticamente el documento al que apunta la DBRef. O sea, que evitas tener que hacer tu la consulta manual para recuperar el autor, pero la sigue haciendo igual, con lo que no es tan eficiente como en el caso de embeber.
En la docu oficial tiene más info y recomendaciones para saber cuando usar una forma y otra: http://www.mongodb.org/display/DOCS/Schema+Design