2014-12-11 3 views
0

До сих пор я встречал способы выбора случайных документов, но моя проблема немного больше pickle.So здесь идетсовет MongoDB запросов для взвешенной рандомизированной агрегации

У меня есть коллекция, которая содержит сказать 1000+ документы (продукты) говорят, каждый документ имеет более или менее общий формат .say для простоты это

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

GroupID представляет собой число в диапазоне от 1 говорит до 20, обозначающее продукт принадлежит к той группе.

Теперь, если мой запрос вход что-то вроде массива {groupid-> вес} для например {[{ "2": 4}, { "7": 6}]} и сказать другой параметр п (= 10 говорят) Тогда мне нужно, чтобы быть в состоянии выбрать 4 случайные документы, которые принадлежат к GroupID 2 и 6 случайных документов, которые принадлежат к GroupID 7.

Единственное решение я могу думать для запуска подпрограмм «m», где m - длина массива в запросе. Как сделать это эффективным способом в MongoDB, используя, вероятно, Mapreduce.

ответ

1

Подборка n случайных документов для каждой группы.

  • Группируйте записи по полю groupid. Исчислите groupid как key и record как value.
  • Для каждой группы выберите n случайные документы из массива values.

Пусть,

var parameter = {"5":1,"6":2}; // groupid-> вес, сохранить его как объект.

быть входным для функции уменьшения карты.

Функция map, излучайте только те группы, которые мы предоставили как parameter.

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 объекта в области видимости.

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 в картину, необходимо указать количество документов для каждой группы как отношение, или же этот параметр не является необходимо вообще.

+0

Это кажется полезным. – humblerookie

Смежные вопросы