MongoDB查询加权随机聚合的建议

时间:2014-12-11 09:41:11

标签: mongodb mongodb-query aggregation-framework database

到目前为止,我已经遇到了选择随机文档的方法,但我的问题更多的是一个泡菜。所以这里去了

我有一个包含 1000 + 文件(产品)的集合 说每个文档都有一个或多或少的通用格式。为简单起见,它是

{"_id":{},"name":"Product1","groupid":5}

groupid是1到20之间的数字,表示该产品属于该组。

现在,如果我的查询输入类似于{groupid-> weight}的数组,例如 {[{" 2":4},{& #34; 7":6}]} 并说出另一个参数 n(= 10说)然后我需要能够选择 4个随机文档属于groupid 2和属于groupid 7的 6个随机文档

我能想到的唯一解决方案就是跑步' m'子查询,其中m是查询输入中的数组长度。 如何使用Mapreduce在MongoDB中实现这种高效的方式。

1 个答案:

答案 0 :(得分:1)

为每个小组挑选n份随机文件。

  • groupid字段对记录进行分组。将groupid作为key发出 以及recordvalue
  • 对于每个组,从n数组中选择values个随机文档。

让,

var parameter = {"5":1,"6":2}; // groupid-> weight,将其保存为Object。

是地图缩小功能的输入。

map函数,仅发出我们提供为parameter的组ID。

var map = function map(){
if(parameter.hasOwnProperty(this.groupid)){
   emit(this.groupid,this);
 }
}

每个组的reduce函数根据parameter中的scope对象获取随机记录。

var reduce = function(key,values){
    var length = values.length;
    var docs = [];
    var added = [];
    var i= 1;
    while(i<=parameter[key]){
        var index = Math.floor(Math.random()*length);
        if(added.indexOf(index) == -1){
         docs.push(values[index]);
         added.push(index);
         i++;
        }
        else{
            i--;
        }
    }
    return {result:docs};
}

通过在范围内传递parameter对象来调用集合上的map reduce。

db.collection.mapReduce(map,
               reduce,
              {out: "sam",
               scope:{"parameter":{"5":1,"6":2,"n":10}}})

获取转储输出:

db.sam.find({},{"_id":0,"value.result":1}).pretty()

当您将参数n放入图片时,您需要指定每个组的文档数量作为比率,否则根本不需要该参数。