Суммируйте все ключи документа динамически - PullRequest
0 голосов
/ 06 июня 2018

У меня есть следующая структура моего документа:

{"x":1, "y":1}

, где ключи неизвестны и динамичны.Я хочу, чтобы результат, который объединяет все поля.Пример: если моя коллекция состоит из:

{"x":1, "y":10}
{"x":1, "y":20}
{"x":2 , "z":13}

Я хочу, чтобы результат был

{"sum":{"x":4, "y":30,"z":13}

Как это возможно?

1 Ответ

0 голосов
/ 06 июня 2018

С MongoDB 3.6 вы можете использовать $objectToArray и $arrayToObject, чтобы разделить объекты и накапливать:

db.collection.aggregate([
 { "$project": {
    "data": {
      "$filter": {
        "input": { "$objectToArray": "$$ROOT" },
        "cond": { "$ne": [ "$$this.k", "_id" ] }
      }
    }
 }},
 { "$unwind": "$data" },
 { "$group": {
   "_id": "$data.k",
   "v": { "$sum": "$data.v" }
 }},
 { "$sort": { "_id": 1 } },
 { "$group": {
   "_id": null,
   "data": { "$push": { "k": "$_id", "v": "$v" } }
 }},
 { "$replaceRoot": { 
   "newRoot": { "$arrayToObject": "$data" }
 }}
])

Возвращает:

{ "x" : 4, "y" : 30, "z" : 13 }

То же самое в основном с mapReduce(), если у вас нет MongoDB, поддерживающей эти операторы:

db.collection.mapReduce(
  function() {
    var doc = this;
    delete doc._id;
    emit(null, doc);
  },
  function(key,values) {
    var output = {};
    values.forEach(value =>
      Object.keys(value).forEach(k => {
        if (!output.hasOwnProperty(k))
          output[k] = 0;
        output[k] = output[k] + value[k];
      })
    );
    return output;
  },
  { "out": { "inline": 1 } }
)

Немного другой вывод в стиле mapReduce:

    {
            "_id" : null,
            "value" : {
                    "x" : 4,
                    "y" : 30,
                    "z" : 13
            }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...