Obtener registros aleatorios con MongoDB

En una base de datos NoSQL como es MongoDB nos asaltan dudas constantemente. En este caso, ¿Cómo obtener un único registro aleatorio? A continuación os detallo como obtener este dato.

Para obtener un registro aleatorio debemos de realizar una consulta de un único elemento pero saltando los x primeros registros. De esta forma obtendremos el resultado. Nada mas fácil que verlo con un ejemplo. Para ello pondré 2 ejemplos uno directamente haciendo la consulta sobre MongoDB y otro utilizando ODM de Mongoose.

En MongoDB se haría de la siguiente forma.

db.games.find().limit(-1).skip( _rand() * db.games.count() )

Si tenemos una tabla games con un listado de juegos y queremos seleccionar un juego aleatorio, lo podríamos hacer así. Seleccionamos todos los juegos, establecemos el limit a -1 y saltamos un aleatorio.

Otro método sería utilizando mongoose, este ya solo como programación.

mongooseModel.count().exec(function(err, resultCount) {
  var rand = Math.floor(Math.random() *resultCount);
  mongooseModel.findOne().skip(rand).exec(function(err, result) {
    console.log(result);
  });
});

Como podemos ver, es un lo mismo que hacerlo directamente sobre MongoDB pero añadiendo algo de complejidad en el proceso por las llamadas asíncronas. En primer lugar deberemos obtener el número de resultados, una vez los tengamos, podemos calcular el aleatorio y obtener con findOne el resultado que queremos.

Ya para terminar un buen ejemplo de como utilizar este código, es utilizando where para filtrar los resultados, que deberemos aplicar tanto a la hora de obtener el contador como cuando buscamos el resultado, ya que si no lo aplicamos en conjunto, puede fallarnos todo el código.

var where = { screenshots: {$exists: true, $not: {$size: 0}} };

mongooseGameModel.count().where(where).exec(function(err, gameCount) {
  var rand = Math.floor(Math.random() * gameCount);

  mongooseGameModel.findOne().where(where).skip(rand).populate('developer').exec(function(err, game) {
    res.locals.randomGame = game;
    next();
  });
});

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *