Larry Price

And The Endless Cup Of Coffee

Fetching Random Mongoose Objects the Simple Way

| Comments

As I venture through the land of NodeJS, I’ve found the wonder and magic of NPM, a package management tool for Javscript similar to ruby’s gems. Although there are nearly 100,000 packages on the main npmjs site (94,553 at time-of-writing), it seems there are still niches to be filled.

Recently, while working on a top secret side-project, I wanted to grab a random object from a MongoDB collection. I used the highly-extensible mongoose to set up my models and just needed to find a package somewhere with the desired functionality. I found such a package called mongoose-random, but, unfortunately, I was never able to get this plugin to work correctly. The plugin in question also needed to insert new columns on your tables, which I didn’t really want. So I decided to create a new package.

mongoose-simple-random is an incredibly easy way to include a random accessor on your mongoose models. All that’s required is adding the plugin to the schema before compiling the model:

test.js
1
2
3
4
5
6
7
8
var random = require('mongoose-simple-random');

var s = new Schema({
  message: String
});
s.plugin(random);

Test = mongoose.model('Test', s);

Now I can ask the model for a single random element of the Test model with a single call to findOneRandom:

find_one.js
1
2
3
4
5
6
var Test = require('./test');

Test.findOneRandom(function(err, element) {
  if (err) console.log(err);
  else console.log(element);
});

Need to find more than one? Use findRandom to get an array:

find_five.js
1
2
3
4
5
6
var Test = require('./test');

Test.findRandom({}, {}, {count: 5}, function(err, results) {
  if (err) console.log(err);
  else console.log(results);
});

Zowee! Just like the default find methods, you can pass in optional filters, fields, and options:

find_five_with_optionals.js
1
2
3
4
5
6
7
8
9
var Test = require('./test');

var filter = { type: { $in: ['education', 'engineering'] } };
var fields = { name: 1, description: 0 };
var options = { skip: 10, limit: 10, count: 5 };
Test.findRandom(filter, fields, options, function(err, results) {
  if (err) console.log(err);
  else console.log(results);
});

Given 1000s of objects, performance is excellent. I haven’t tested it on larger-scale databases, but I wouldn’t mind seeing some performance tests in the future.