2

I have a node.js project and I need to get 8 random documents which are not sequential from my mongoDB database using Mongoose.

My Schema:

var mongoose = require('mongoose');
var random = require('mongoose-simple-random');


var schema = new mongoose.Schema({
    title: String,

    width:String,
    height:String,

});
var Images = mongoose.model('Images', schema);


Images.count().exec(function (err, count) {

  // Get a random entry
  var random = Math.floor(Math.random() * count)

  // Again query all users but only fetch one offset by our random #
  Images.find({}).limit(8).skip(random).exec(
    function (err, result) {
      // Tada! random user
      console.log(result)
        //res.send(results);
    })
})

module.exports = {
    Images: Images
};

When calling the function in my route file (Main.js):

    var Images = require('../models/images.js');



app.get('/homepage', function(req, res){
  var rand = Math.floor(Math.random() * 10000);
    Images.find({}).limit(8).skip(rand).exec(function(err, docs){

        res.render('homepage', {images: docs});
    });
});

How would I call the 'find' function in my model from my main.js route file?

user
  • 395
  • 2
  • 11
  • 28
  • Possible duplicate of [How to find random record in Mongoose](http://stackoverflow.com/questions/39277670/how-to-find-random-record-in-mongoose) – Bertrand Martel Feb 27 '17 at 18:02
  • @BertrandMartel I have updated my question with a working model, but would you know how I'd call the model function from my router file in order to render the data in the view? – user Feb 28 '17 at 10:38
  • possible duplicate of https://stackoverflow.com/questions/14644545/random-document-from-a-collection-in-mongoose – Deepak Jul 31 '19 at 10:38

1 Answers1

0

You could use the following to get unique items with $sample but grouping by _id to remove possible duplicates in the random result :

db.images.aggregate([{
    $sample: { size: 100 }
}, {
    $group: {
        _id: "$_id",
        document: { $push: "$$ROOT" }
    }
}, {
    $limit: itemCount
}, {
    $unwind: "$document"
}])

For the structure of your code, you could define a static method getRandomItems, storing your mongoose object in express app.db and calling the mongoose object from your router with req.app.db :

model.js

'use strict';

exports = module.exports = function(app, mongoose) {

    var schema = new mongoose.Schema({
        title: String,

        width: String,
        height: String,

    });

    schema.statics.getRandomItems = function(itemCount, cb) {

        this.aggregate([{
            $sample: { size: 100 }
        }, {
            $group: {
                _id: "$_id",
                document: { $push: "$$ROOT" }
            }
        }, {
            $limit: itemCount
        }, {
            $unwind: "$document"
        }], cb);
    };

    app.db.model('Images', schema);
};

app.js

'use strict';

var mongoose = require('mongoose'),
    express = require('express');

var app = express();

app.db = mongoose.createConnection("mongodb://localhost/testDB");

// config data models
require('./models')(app, mongoose);
require('./routes')(app);

app.listen(8080, function() {

});

routes.js

'use strict';

exports = module.exports = function(app) {

    // BboxAPI
    app.get("/random", function(req, res) {

        req.app.db.models.Images.getRandomItems(8, function(err, result) {
            if (err) {
                console.log(err);
                res.status(500).json(err);
            } else {
                res.status(200).json(result);
            }
        });
    });
};
Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159