Я хочу создать функцию Schema.statics.random
, которая доставит мне случайный элемент из коллекции. Я знаю, что есть пример для родного драйвера MongoDB, но я не могу заставить его работать в Mongoose.
Случайный документ из коллекции в Mongoose
Ответ 1
Я нашел эту статическую функцию 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
NB Я немного изменил код, чтобы сделать его более читаемым.
Ответ 2
Если вы не хотите добавлять код "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
});
});
Ответ 3
Я реализовал плагин для mongoose, который делает это очень эффективно, используя $near query на двух случайно сгенерированных координатах, используя индекс 2dsphere. Посмотрите здесь: https://github.com/matomesc/mongoose-random.
Ответ 4
Для людей, смотрящих на это во времена асинхронности/ожидания, обещаний и т.д.:
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;
};
Ответ 5
Более короткое и, возможно, более производительное решение
(мы не перебираем коллекцию один раз, чтобы сосчитать, а второй - чтобы пропустить элементы, но мангуст может сделать это за кадром):
Используйте агрегат и $ sample:
Model.aggregate([{ $sample: { size: 1 } }])