来自Mongoose集合的随机文档

时间:2013-02-01 10:44:13

标签: javascript node.js mongoose

我想创建一个Schema.statics.random函数,它从集合中获取一个随机元素。我知道有一个本机MongoDB驱动程序的例子,但我无法在Mongoose中使用它。

10 个答案:

答案 0 :(得分:27)

我在GitHub Gist中找到了这个Mongoose Schema静态函数,它可以实现你所追求的目标。它计算集合中的文档数量,然后在跳过随机数量后返回一个文档。

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 我修改了一些代码以使其更具可读性。

答案 1 :(得分:11)

如果您不想添加"测试类似"代码进入您的架构,这使用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 

  });

});

答案 2 :(得分:6)

我已经为mongoose实现了一个插件,它使用2dsphere索引在两个随机生成的坐标上使用$ near查询以非常有效的方式执行此操作。请在此处查看:https://github.com/matomesc/mongoose-random

答案 3 :(得分:1)

对于在async / await,promises等时候看这个的人:

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

答案 4 :(得分:1)

现在推荐使用 Model.estimatedDocumentCount()。对于名为 Item 的模型,函数的轮廓将是:

const Item = require('../your/path/to/Model/Item')

async function getRandomItem() {
   const numItems = await Item.estimatedDocumentCount()
   const rand = Math.floor(Math.random() * numItems)
   const randomItem = await Item.findOne().skip(rand)
   return randomItem
}

答案 5 :(得分:0)

更短,也许更高效的解决方案
(我们不会一次遍历整个集合以进行计数,而第二遍却不会跳过元素,但是猫鼬可能会在幕后进行此操作):

使用aggregate and $sample

Model.aggregate([{ $sample: { size: 1 } }])

答案 6 :(得分:0)

您可以使用聚合:

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

或者您可以使用npm软件包https://www.npmjs.com/package/mongoose-simple-random

User.findRandom({gender: "male"}, {}, {limit: 10}, function(err, results) { 
    console.log(results); // 10 elements
});

答案 7 :(得分:0)

// Getting estimated document count.
yourModel.estimatedDocumentCount().then((count) => {
  //Random number between 0 and count.
  const rand = Math.floor(Math.random() * count);

  // Finding ONE random document.
  yourModel
    .findOne()
    .skip(rand)
    .then((randomDocument) => {
      console.log(randomDocument);
    });
});

您也可以使用 countDocuments(),但为了性能,建议使用 EstimatedDocumentCount()。

我更喜欢这种方法,因为它得到的是一个文档而不是一个数组。

答案 8 :(得分:0)

  1. 获取集合中的文档总数。
  2. 定义一个介于 1 和文档总数之间的随机数。
  3. 获取一个文档并跳过该随机数。
const total = await model.countDocuments();
const skip = Math.floor(Math.random() * total) + 1;
const randomDoc = await model.findOne({}).skip(skip).exec();

答案 9 :(得分:0)

给出3个随机文件的命令:

db.collection.aggregate([{$sample:{limit: 3}}])

快递线路获得4个随机文件。我认为它适用于最新版本的 mongo。

db.aggregate([{$sample:{limit: 4}}])

查看this link了解更多信息