对不同结构的文档进行求和操作



我试图使用聚合管道能够做一个报告表(排序,分页等)使用mongodb为我的后端。我遇到了一个问题,我的模式是不一样的,但我需要添加所有的值。我试图使用unwind命令,但它只在数组中工作,所以没有其他选择。

样本文件

{
  "_id": "first",
  "apple": 6,
  "pears": 7,
  "total_fruits": "13"
},
{
  "_id": "second",
  "apple": 6,
  "bananas": 2,
  "total_fruits": "8"
}

预期的结果

{
  "_id": "result",
  "apple": 12,
  "pears": 7,
  "bananas": 2,
  "total_fruits": "21"
}

与其聚合,不如使用mapReduce()

function sumKeyFromCollection(collectionName, keyName) {
    map = function() { emit(keyName, this[keyName]); }
    red = function(k, v) {
      var i, sum = 0;
      for (i in v) {
        sum += v[i];
      }
      return sum;
    }
    return db[collectionName].mapReduce(map, red, {out : {inline: 1}});
}

对于您的示例文档:

{
  "_id": "first",
  "apple": 6,
  "pears": 7,
  "total_fruits": "13"
},
{
  "_id": "second",
  "apple": 6,
  "bananas": 2,
  "total_fruits": "8"
}

您可以在每个字段名上调用该函数:

console.log(sumKeyFromCollection("collectionName", "apple"));
> { "_id": "...", "apple": 12 }

然后分别使用它们生成最终文档:

var fruits = [ "apple", "bananas", "total_fruits" ];
var results = []; 
for (var i = 0; i < fruits.length; i++) {
  results.push(sumKeyFromCollection("collectionName", fruits[i]));
}

EDIT此外,要以编程方式获取集合中的每个字段名:

function getAllCollectionFieldNames(collectionName) {
    mr = db.runCommand({
      "mapreduce" : collectionName,
      "map" : function() {
        for (var key in this) { emit(key, null); }
      },
      "reduce" : function(key, stuff) { return null; }, 
      "out": "my_collection" + "_keys"
    });
    db[mr.result].distinct("_id");
}

返回唯一字段名的数组(即使它们只出现在一个文档中)。

最新更新