从mongodb集合中检索唯一的随机项?

从mongodb集合中检索唯一的随机项?,mongodb,random,Mongodb,Random,我运行了一个IRC机器人,我有一个函数,它使用Math.random从我的Mongodb集合返回1个随机url 我希望对其进行重构,以返回x个唯一的项目,并且对于url获取命令.getlinks的每次后续调用,我希望它保持所有内容的唯一性,以便用户不会看到相同的链接,除非已返回所有可能的链接 是否有一些算法或本机mongodb函数可以用于此 下面是一个示例场景: 我总共收藏了9张唱片。它们有一个\u id和url字段 user a: .getlinks() bot returns: http:/

我运行了一个IRC机器人,我有一个函数,它使用Math.random从我的Mongodb集合返回1个随机url

我希望对其进行重构,以返回x个唯一的项目,并且对于url获取命令
.getlinks
的每次后续调用,我希望它保持所有内容的唯一性,以便用户不会看到相同的链接,除非已返回所有可能的链接

是否有一些算法或本机mongodb函数可以用于此

下面是一个示例场景:

我总共收藏了9张唱片。它们有一个
\u id
url
字段

user a: .getlinks()
bot returns: http://unique-link-1, http://unique-link-2, http://unique-link-3, http://unique-link-4

user a: .getlinks()
bot returns: http://unique-link-5, http://unique-link-6, http://unique-link-7, http://unique-link-8

user a: .getlinks()
bot returns: http://unique-link-9, http://unique-link-6, http://unique-link-1, http://unique-link-3
背景资料:

  • 总共有大约200个链接。我估计到明年年底,这个数字将增长到5000个左右
目前我唯一能想到的是保留一个所有返回项目的数组,一次从集合中获取所有项目,并随机获取4次,确保它是唯一的,并且尚未显示

var shown = [], amountToReturn = 4;
function getLinks() {
   var items = links.find(), returned = [];
   for ( var i = 0; i<amountToReturn; i++ ) {
      var rand = randItem( items );
      if ( shown.indexOf( rand.url ) == -1 && shown.length < items.length ) ) {
         returned.push( rand.url );
      }
   }
   message.say( returned.join(',') );
}
var显示=[],amountToReturn=4;
函数getLinks(){
var items=links.find(),返回=[];

对于(var i=0;i,您应该在此处找到一些可能的选项,以从集合中获取随机项

另一种有趣的方法记录在这里

上面提到的方法基本上是使用Math.random()在文档上创建一个新的键/值


在堆栈溢出问题上,有很多形式提出了这个问题。最流行的问题是——它有很好的响应。也就是说,我认为思考这个问题的最好方法不是考虑获取一个随机文档,而是随机地对结果集进行随机化。请参阅。
> db.docs.drop()
> db.docs.save( { key : 1, ..., random : Math.random() } )
> db.docs.save( { key : 1, ..., random : Math.random() } )
> db.docs.save( { key : 2, ..., random : Math.random() } )
... many more insertions with 'key : 2' ...
> db.docs.save( { key : 2, ..., random : Math.random() } )
...
// map
function() { 
    emit(0, {k: this, v: Math.random()}) 
}

// reduce
function(k, v) {
  var a = []
  v.forEach(function(x) {
    a = a.concat(x.a ? x.a : x)
  })
  return {a:a.sort(function(a, b) {
    return a.v - b.v;
  }).slice(0, 3 /*how many records you want*/)}; 
}

// finalize
function(k, v) {
  return v.a.map(function(x) {
    return x.k
  })
}