Вложенная группа по функции с MongoDB - PullRequest
3 голосов
/ 21 мая 2011

Я довольно новичок в MongoDB, долгое время работал с MySQL и столкнулся с небольшим препятствием.

С учетом приведенных ниже примеров TeamID Day OrderAmount
100 4/1 50
100 4/1 40
200 4/2 50
100 4/2 20

Я пытаюсь найти среднюю сумму командного заказа в день. Я могу сделать простой запрос, используя функцию mapReduce, чтобы создать группу с TeamId & Day. Итак, теперь у меня есть:

TeamID Day AvgAmount
100 4/1 45
200 4/2 50
100 4/2 20

Теперь я пытаюсь свернуть эти данные, чтобы получить среднюю сумму заказа для команды в день, которая будет:

день AvgAmount
4/1 47,5
4/2 35

Я могу сделать это легко с MySQL, но мне сложно понять, как это сделать с MongoDB, не делая это вручную на стороне приложения, а не с MongoDB.

Ответы [ 2 ]

4 голосов
/ 21 мая 2011

Вы можете рассчитать эти агрегаты либо с помощью функции map-Reduce, либо с помощью функции group () .Я использую group (), потому что это немного проще и быстрее, однако вы должны использовать map-lower, если вам нужно распределить запрос по изолированному кластеру.

Сначала загрузите данные:

db.orders.insert( { teamid: 100, date: "4/1", amount: 50 })
db.orders.insert( { teamid: 100, date: "4/1", amount: 40 })
db.orders.insert( { teamid: 200, date: "4/2", amount: 50 })
db.orders.insert( { teamid: 100, date: "4/2", amount: 20 })

Для команды в день:

db.orders.group({
    key: { teamid: true, date: true },
    reduce: function(doc, out) { out.sum += doc.amount; out.count++; },
    initial: { sum: 0, count: 0 },
    finalize: function(out) { out.average = out.sum / out.count }
});

Чтобы свернуть ежедневные агрегаты, просто измените ключ:

db.orders.group({
    key: { date: true },
    reduce: function(doc, out) { out.sum += doc.amount; out.count++; },
    initial: { sum: 0, count: 0 },
    finalize: function(out) { out.average = out.sum / out.count }
});
0 голосов
/ 22 мая 2011

После небольшого исследования я смог найти решение.Я не удовлетворен тем, что это наиболее оптимизированное решение из-за того, что он новичок в MongoDB и отображает / сокращает мышление, поэтому, если у кого-то есть что-то лучше, пожалуйста, поправьте меня.В частности, я не смог получить длину объекта arr_team, поэтому мне нужно было увеличить счетчик.

Функция уменьшения:


    function(doc, prev) { 
      var retVal  = {team_count: 0, day_total: 0};

      if(!prev.arr_team[doc.team_id]) {
        prev.arr_team[doc.team_id] = 0;
        prev.team_count++;
      }

      prev.arr_team[doc.team_id]++;

      prev.order_count++; 
      if(doc.total_amount)
         prev.total_amount += doc.total_amount 

      return retVal;
    }

Завершение:


function(out) {
      out.avg_team_order_amount = out.total_amount/out.team_count;
    }
...