Random document from a collection in Mongoose

后端 未结 6 2091
北恋
北恋 2020-12-02 23:45

I want to create a Schema.statics.random function that gets me a random element from the collection. I know there is an example for the native MongoDB driver, b

相关标签:
6条回答
  • 2020-12-02 23:52

    You can use aggregate:

    User.aggregate([
        {$match: {gender: "male"}},
        {$sample: {size: 10}}
    ], function(err, docs) {
        console.log(docs);
    });
    

    Or you can use npm package https://www.npmjs.com/package/mongoose-simple-random

    User.findRandom({gender: "male"}, {}, {limit: 10}, function(err, results) { 
        console.log(results); // 10 elements
    });
    
    0 讨论(0)
  • 2020-12-02 23:54

    For people looking at this in times of async/await, promises etc.:

    MySchema.statics.random = async function() {
      const count = await this.count();
      const rand = Math.floor(Math.random() * count);
      const randomDoc = await this.findOne().skip(rand);
      return randomDoc;
    };
    
    0 讨论(0)
  • 2020-12-02 23:57

    A shorter and maybe more performant solution
    (we don't iterate through the collection once to count and a second time to skip elements, but mongoose might do that behind the scenes):

    Use aggregate and $sample:

    Model.aggregate([{ $sample: { size: 1 } }])
    
    0 讨论(0)
  • 2020-12-02 23:58

    I found this Mongoose Schema static function in a GitHub Gist, which should achieve what you are after. It counts number of documents in the collection and then returns one document after skipping a random amount.

    QuoteSchema.statics.random = function(callback) {
      this.count(function(err, count) {
        if (err) {
          return callback(err);
        }
        var rand = Math.floor(Math.random() * count);
        this.findOne().skip(rand).exec(callback);
      }.bind(this));
    };
    

    Source: https://gist.github.com/3453567

    NB I modified the code a bit to make it more readable.

    0 讨论(0)
  • 2020-12-02 23:58

    I've implemented a plugin for mongoose that does this in a very efficient way using a $near query on two randomly generated coordinates using a 2dsphere index. Check it out here: https://github.com/matomesc/mongoose-random.

    0 讨论(0)
  • 2020-12-03 00:01

    If you are not wanting to add "test like" code into your schema, this uses Mongoose queries.

    Model.count().exec(function(err, count){
    
      var random = Math.floor(Math.random() * count);
    
      Model.findOne().skip(random).exec(
        function (err, result) {
    
          // result is random 
    
      });
    
    });
    
    0 讨论(0)
提交回复
热议问题