найти - mongodb проекция



Как суммировать значение ключа по всем документам в коллекции MongoDB (3)

У меня есть коллекция в MongoDB:

{ "_id" : ObjectId("4d2407265ff08824e3000001"), "subida" : 3.95 }
{ "_id" : ObjectId("4d2551b4ae9fa739640df821"), "subida" : 6.03 }
{ "_id" : ObjectId("4d255b115ff08821c2000001"), "subida" : 5.53 }
{ "_id" : ObjectId("4d25e8d55ff08814f8000001"), "subida" : 1.96 }

Как я могу суммировать значение ключа, например, "subida" , по всем документам? С приведенными выше документами я должен получить что-то вроде:

{ "subida" : 17.47 }

https://src-bin.com


Answer #1

В этом случае агрегация намного проще и эффективнее, чем mapReduce:

db.collection.aggregate({
    $group: {
        _id: '',
        subida: { $sum: '$subida' }
    }
 }, {
    $project: {
        _id: 0,
        subida: '$subida'
    }
})
  1. используйте $ group с $ sum для вычисления суммы
  2. использовать проектный оператор $ project для удаления ключа id, требуемого оператором $ group

Answer #2

Вариант 0: использовать конвейер агрегации MongoDB
[NB: эта опция была добавлена ​​долгое время после того, как этот вопрос был задан, но сейчас это правильный подход]

Вариант 1. Запросите все записи, верните только поле субиды из Mongo и добавьте их, итерации по стороне клиента Mongo.

Вариант 2: напишите команду уменьшения карты, которая испускает только поле subdia (тот же ключ для всех), а затем команду уменьшения, которая их суммирует.

Вариант 3: используйте db.eval для запуска javascript на сервере: http://www.mongodb.org/display/DOCS/Server-side+Code+Execution

Вариант 4: накапливайте значения «субида» при вставке значений в свою коллекцию, чтобы у вас была актуальная общая сумма, когда вам это нужно. Вы можете сохранить общее количество в другом документе и использовать атомные «обновления, если текущие» операции для его обновления: http://www.mongodb.org/display/DOCS/Atomic+Operations


Answer #3

Я лично выполняю mapreduce в коллекции:

map - простая функция, излучающая поле «субида». Ключ должен совпадать, если вам нужна одна сумма; результат после уменьшения приведет к единственному объекту {<key>: <sum>} , при этом <key> будет тем значением, которое вы предоставили в испускании.

map = function() { emit(<key>, this.subida); }

сокращение - также простая функция, суммирующая их:

red = function(k, v) {
  var i, sum = 0;
  for (i in v) {
    sum += v[i];
  }
  return sum;
}

Затем вы можете вызвать mapreduce в своей коллекции <mycollection> :

res = db.<mycollection>.mapReduce(map, red);

Которая создаст временную новую коллекцию, которую вы можете манипулировать, как и любая другая коллекция. Значение, возвращаемое mapReduce, содержит несколько значений в отношении mapReduce, таких как время, статус ..., а также временные параметры. имя коллекции, созданное в поле «результат». Чтобы получить нужные значения, вы должны запросить эту коллекцию:

db[res.result].find()

Что должно дать вам объект {<key>: <sum>} .

Если вы запустите MongoDB 1.7.4 или выше, вы можете сэкономить немного хлопот, попросив MongoDB напрямую вернуть результат, не создавая коллекцию:

db.<mycollection>.mapReduce(map, red, {out : {inline: 1}});




nosql