mongo db (3): leer documentos

Primera parte sobre la recuperación de documentos en mongo

Maria Szollosi

archivado en: JavaScript / 16 marzo, 2015 / taller:

En la entrada anterior de esta serie dedicada a mongodb vimos cómo hacer consultas básicas. Ahora toca profundizar en las distintas operaciones CRUD, es decir, para crear (create), leer (read), actualizar (update) y borrar (delete) las cosas. Empezamos con las lecturas, esto es, con la recuperación de datos, un tema que nos llevará dos entradas, esta y la siguiente.

Para hacer pruebas podemos crear una base datos llamada laboratorio o cómo sea con use e insertar unos cuantos documentos en una colección llamada bazinga. Cada uno tendrá dos claves, una numérica incremental y otra un string generado aleatoriamente. Y recordemos que eso lo podemos hacer con js, que es un lenguaje que entiende el shell de mongodb.

> use laboratorio

for (var i=0; i<56; i++) {

db.bazinga.insert(

{"foo":i,

"bar":Math.random().toString(36).substring(7)}

);

}

Y con todo preparado ya, empezamos ^^.

1. find() y findOne()

Ya sabemos que para recuperar todos los documentos de una colección podemos usar el método find().

> db.bazinga.find()

Y, para especificar criterios de búsqueda simples, basta con pasarle a find() la clave y el valor por los que debe buscar.

> db.bazinga.find({"foo":5})

{ "_id" : ObjectId("55021c9d3571e1dc735525a9"), "foo" : 5, "bar" : "0s6ge23ayvi" }

Sin embargo, si solo necesitamos recuperar un documento, es mejor utilizar findOne(), pues deja de buscar cuando lo encuentra.

> db.bazinga.findOne({"foo":5})

Si no indicamos lo contrario, en la consulta nos devuelven todo el documento completo, incluido el id autogenerado por mongo; pero podemos indicar qué claves son las que nos interesan exactamente.

db.bazinga.findOne({}, {"foo":5})

Así nos sigue trayendo el id. Para quitar esta clave o cualquier otra hay que poner un 0 en el valor.

db.bazinga.findOne({}, {"foo":5, "_id":0})

2. Búsquedas comparativas

Mongo también cuenta con cinco operadores que nos permiten definir criterios de comparación en las búsquedas:

  • $lt (litte that): menor que.
  • $lte (litte / equal): menor o igual que.
  • $gt (greater that): mayor que.
  • $gte  (greater / equal): mayor o igual que.
  • $ne (not equal): no igual a.

Por ejemplo, así nos devuelve todos los resultados donde foo es mayor que 50.

> db.bazinga.find({ foo: {"$gte":50} })

Y así aquellos donde foo no es 1.

db.bazinga.find({foo: {"$ne":1}})

Y, claro, también tiene operadores lógicos.

Para el or, es decir, para que encuentre este o este otro resultado, hay dos operadores: $in, que compara valores para una sola clave, y $or, que compara varias claves.

Así, por ejemplo, encontraríamos todos los documentos cuya clave foo vale 1 o 2.

> db.bazinga.find({foo: {"$in": [1, 2]}})

Para buscar justo lo contrario, es decir, para encontrar los documentos cuyas claves no son 1 o 2, podemos usar el operador $nin.

$or, en cambio, nos sirve para definir varias claves en los criterios de búsqueda en un array. Así encontraríamos los documentos cuya clave foo es 5 o los que su clave bar vale vjhndmcmcxr.

> db.bazinga.find({"$or": [{"foo":5}, {"bar":"vjhndmcmcxr"}] })

{ "_id" : ObjectId("55021c9d3571e1dc735525a5"), "foo" : 1, "bar" : "vjhndmcmcxr" }

{ "_id" : ObjectId("55021c9d3571e1dc735525a9"), "foo" : 5, "bar" : "0s6ge23ayvi"}

Además existe el metacondicional $not, que se puede aplicar en cualquiera de los casos anteriores para indicar que no se devuelvan esas coincidencias (equivale al ! de js).

3. Consultas y tipos

En función del valor de las claves, ya sean estas cadenas, números, arrays, expresiones, etcétera, las consultas tienen sus propias características.

Para los valores null se produce un fenómeno curioso. Para que se entienda en la práctica, vamos a insertar un documento en nuestra base datos con una propiedad nueva con valor null.

db.bazinga.insert({"foo" : 1, "bar" : "vjhndmcmcxr", "awesome":null})

Si ahora buscamos los documentos donde awesome vale null...

db.bazinga.find({"awesome":null})

... Nos trae el que acabamos de crear y ¡todos los demás!, ya que considera que una propiedad que no existe tiene el valor null. Para que solo busque los documentos donde sí existe esa propiedad hay que añadir el condicional $exists.

db.bazinga.find({"awesome" : { "$in": [null], "$exists": true}})

Mongo también nos permite definir expresiones regulares para realizar las búsquedas. Así encontraríamos, por ejemplo, el primer documento cuya propiedad bar empiece por v.

db.bazinga.findOne({"bar" : /^v/})

Con los arrays también podemos hacer cosas muy chulas. Añadamos tres documentos más a la colección:

> db.bazinga.insert({"hagaBasin":[1, 2, 3]});

> db.bazinga.insert({"hagaBasin":[1, 6, 7]});

> db.bazinga.insert({"hagaBasin":[4, 8, 9, 10, 11]});

Los arrays pueden tratarse como si cada elemento fuera una clave.

> db.bazinga.find({"hagaBasin":1});

{ "_id" : ObjectId("5505306b4dea9391e2f0a6c6"), "hagaBasin" : [ 1, 2, 3 ] }

{ "_id" : ObjectId("5505306b4dea9391e2f0a6c7"), "hagaBasin" : [ 1, 6, 7 ] }

Si anteponemos el operador $all, deben coincidir todos los elementos indicados en el array que le sigue.

db.bazinga.find({hagaBasin: {$all:[1, 2]}})

{ "_id" : ObjectId("5505306b4dea9391e2f0a6c6"), "hagaBasin" : [ 1, 2, 3 ] }

Se tiene en cuenta el orden en la definición de los parámetros. Por ejemplo, esto nos devolvería un resultado, nuestro primer documento:

> db.bazinga.find( {"hagaBasin":[1, 2, 3] } )

Pero este, con los ítems cambiados de sitio, no devolvería nada.

db.bazinga.find( {"hagaBasin":[3, 2, 1] } )

Además, podemos buscar por su tamaño con el operador $size.

> db.bazinga.find( {"hagaBasin":{$size:5} })

{ "_id" : ObjectId("5505306c4dea9391e2f0a6c8"), "hagaBasin" : [ 4, 8, 9, 10, 11] }

Con el operador $slice podemos seleccionar una parte del array, igual que con el slice normal de js.

db.bazinga.findOne({"_id": ObjectId("5505306c4dea9391e2f0a6c8")}, {"hagaBasin" {"$slice":[1, 3]}})

"_id" : ObjectId("5505306c4dea9391e2f0a6c8"),

"hagaBasin" : [8, 9, 10]

Y ya para terminar decir que para seleccionar documentos que contienen jasonakos, si no queremos ponerlos completos en el find, basta con acceder a las claves con el operador $elemMatch:

db.bazinga.find({"jasonako": {$elemMatch" : {foo: "bar", "hagaBasin": 7} } });

Bueno, pues por hoy ya está bien, que menudo tocho de post :P. En la próxima entrada de esta serie sigo con el find().

|| Tags: , , , ,

valoración de los lectores sobre mongo db (3): leer documentos

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 4.7 sobre 5 (3 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Los comentarios están cerrados.