Я хочу создать функцию Schema.statics.random, которая получает случайный элемент из коллекции. Я знаю, что есть пример для родного драйвера MongoDB, но я не могу заставить его работать в Mongoose.

24
user1680104 1 Фев 2013 в 14:44

5 ответов

Лучший ответ

Я нашел эту статическую функцию Mongoose Schema в GitHub Gist, которая должна достичь того, что вам нужно. Он подсчитывает количество документов в коллекции, а затем возвращает один документ после пропуска случайной суммы.

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));
};

Источник: https://gist.github.com/3453567

Внимание! . Я немного изменил код, чтобы сделать его более читабельным.

36
matthewtole 1 Фев 2013 в 11:05

Если вы не хотите добавлять код "test like" в вашу схему, это использует запросы Mongoose.

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

  var random = Math.floor(Math.random() * count);

  Model.findOne().skip(random).exec(
    function (err, result) {

      // result is random 

  });

});
16
Eat at Joes 4 Фев 2015 в 20:59

Я реализовал плагин для mongoose, который делает это очень эффективным способом, используя запрос $ near для двух случайно сгенерированных координат с использованием индекса 2dsphere. Проверьте это здесь: https://github.com/matomesc/mongoose-random.

6
Mihai Tomescu 3 Июл 2013 в 20:50

Более короткое и возможно более эффективное решение
(мы не перебираем коллекцию один раз, чтобы сосчитать, а второй - чтобы пропустить элементы, но мангуст может сделать это за кадром):

Используйте агрегат и $ sample:

Model.aggregate([{ $sample: { size: 1 } }])
3
Ioanna 10 Июл 2019 в 13:55

Для людей, смотрящих на это во времена асинхронности / ожидания, обещаний и т.д .:

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;
};
2
mBeierl 10 Апр 2018 в 21:21