как написать простой запрос агрегации в mongo db 2.0.6 с json API

Только что запустил монго и уже начались проблемы с запросами. у меня есть коллекция под названием «externalTransaction», и я хочу написать эквивалент этого запроса mysql:

select transactionCode, 
       sum(amount) as totalSum, 
       count(amount) as totalCount 
from externalTransaction 
where transactioncode in ('aa','bb','cc') 
group by sum(amount)

ниже моя попытка:

{
 "collectionName": "externalTransaction",
  sort: {transactionCode:-1},
  query: {this._id: {$in:['aa','bb','cc']}},
  mapReduce:{
   'map': 'function(){

        emit(this.transactionCode, this.amount);

   }',
 'reduce': 'function(key, values){
    var result = {count: 0, sum: 0.0};

    values.forEach(function(value) {
      result.count++
       result.sum += value.amount;
    });
    return result;
 }',
   'out' : 'sumAmount'
 }

}

приведенный выше запрос дает мне набор результатов, который выглядит следующим образом:

_id     value.count        value.sum
ct      2.0                NaN
bb      40.0           NaN
fg      71.0           NaN
fd      36.0           NaN
sd      5.0                NaN
as      4.0            NaN
aa      71.0           NaN
df      4.0                NaN
cc      10.0               NaN

Из документации с версией 2.0.6 я пока не могу использовать aggregation framework, так как обрабатывать простые запросы, такие как мой, в монго. спасибо за чтение и извините за тривиальность моего вопроса.


person black sensei    schedule 26.06.2012    source источник


Ответы (1)


У вас несколько ошибок в функциях map и reduce. Во-первых, в map вы выдаете простое число, а в reduce пытаетесь взять amount числа. Бьюсь об заклад, у него нет этого свойства. Во-вторых, выходные данные map и reduce должны быть однородными, поскольку предполагается, что reduce может работать с частично сокращенными результатами. Попробуйте эти функции:

var map = function() {
  emit(this.transactionCode, {sum: this.amount, count: 1})
}

var reduce = function(k, vals) {
  var result = {sum: 0, count: 0};

  vals.forEach(function(v) {
    result.sum += v.sum;
    result.count += v.count;
  });
  return result;
}
person Sergio Tulentsev    schedule 26.06.2012
comment
приятно спасибо за ответ. я думаю, что с вашим предложением у меня что-то работает. но мне интересно, почему фильтр не работает. он по-прежнему выбирает каждую транзакцию. Я тоже сделал что-то не так? - person black sensei; 26.06.2012
comment
@blacksensei: да, это выглядит странно. Разве это не должно быть query: {transactionCode: {$in:['aa','bb','cc']}}? - person Sergio Tulentsev; 26.06.2012
comment
изменил его на query: {transactionCode: {$in:['aa','bb','cc']}}, но все равно тянет все. :( - person black sensei; 26.06.2012
comment
Как вы запускаете это именно? И откуда вы взяли этот синтаксис? - person Sergio Tulentsev; 26.06.2012
comment
Посмотрите примеры здесь: github.com/mongodb/mongo/blob/ мастер/jstests/mr1.js. Попробуйте заставить его работать в оболочке mongo. - person Sergio Tulentsev; 26.06.2012
comment
эй, @sergio, я поставил условие if перед функцией emit в функции карты. это, кажется, работает на данный момент. сейчас проверяю вашу ссылку. спасибо .я отмечаю это как решенное спасибо - person black sensei; 26.06.2012
comment
я запускаю его из ireport, который использует стиль json. дело в том, что с моего терминала ubuntu много чего работает. но когда дело доходит до json, это довольно сложно. Поскольку окончательный запрос должен использоваться ireport, я бы предпочел использовать этот графический интерфейс для написания и проверки запроса. - person black sensei; 26.06.2012
comment
Ну если не работает mongodb - это одно. Если это какой-то сторонний инструмент - это совсем другое. Вы должны были упомянуть об этом раньше, я бы отправил вас в их поддержку :) - person Sergio Tulentsev; 26.06.2012
comment
давайте продолжим обсуждение в чате - person black sensei; 26.06.2012