操作MongoDB结果以动态生成字段名



我正在尝试重组Mongo查询的结果,以使用属性调用"field"中的值作为结果中的键。

我有一个查询,返回的结果如下:

[
{
    "_id" : ObjectId("544ecbf11972fd515fd6306c"),
    "field" : "fieldOne",
    "value" : "fieldOneValue"
},
 "_id" : ObjectId("544ecbf11972fd515fd6307c"),
    "field" : "fieldTwo",
    "value" : "fieldTwoValue",
},
{
 "_id" : ObjectId("544ecbf11972fd515fd6308c"),
    "field" : "fieldThree",
    "value" : "fieldThreeValue"
}
]

有没有一种方法可以得到这样的结果:

{
   fieldOne:fieldOneValue,
   fieldTwo:fieldTwoValue,
   fieldThree:fieldThreeValue
}

使用mapReduce可以做到这一点,因为基本上您需要JavaScript处理来生成动态密钥。

映射非常琐碎:

var mapper = function () {
  var obj = {};
  obj[this.field] = this.value;
  emit(1,obj);
};

减速器只是将所有发射的元素与相同的"关键"值结合在一起:

var reducer = function (key,values) {
  var reduced = {};
  values.forEach(function(value) {
    Object.keys( value ).forEach(function(key) {
      reduced[key] = value[key];
    });
  });
  return reduced;
};

只需调用并获取结果,尽管是以一种非常"mapReduce"的方式,因为输出总是这样:

db.threedocs.mapReduce(mapper,reducer,{ out: { inline: 1 } })
{
    "results" : [
            {
                    "_id" : 1,
                    "value" : {
                            "fieldOne" : "fieldOneValue",
                            "fieldTwo" : "fieldTwoValue",
                            "fieldThree" : "fieldThreeValue"
                    }
            }
    ],
    "timeMillis" : 6,
    "counts" : {
            "input" : 3,
            "emit" : 3,
            "reduce" : 1,
            "output" : 1
    },
    "ok" : 1
}

聚合框架可以更接近更好的输出,但只能处理静态数据,不能"动态"分配未知的密钥名称。但如果你知道该期待什么,你可以这样做:

db.threedocs.aggregate([
    { "$group": {
        "_id": null,
        "fieldOne": {
            "$max": {
               "$cond": [
                   { "$eq": [ "$field", "fieldOne" ] },
                   "$value",
                   0
               ]
            }
        },
        "fieldTwo": {
            "$max": {
               "$cond": [
                   { "$eq": [ "$field", "fieldTwo" ] },
                   "$value",
                   0
               ]
            }
        },
        "fieldThree": {
            "$max": {
               "$cond": [
                   { "$eq": [ "$field", "fieldThree" ] },
                   "$value",
                   0
               ]
            }
        }
    }},
    { "$project": {
        "_id": 0,
        "fieldOne": 1,
        "fieldTwo": 1,
        "fieldThree": 1
    }}
])

输出更好:

{
    "fieldOne" : "fieldOneValue",
    "fieldTwo" : "fieldTwoValue",
    "fieldThree" : "fieldThreeValue"
}

在任何一种情况下,操作都是相当琐碎的,并且没有真正考虑到"字段"的多个值的存在或如何处理它们。在现实世界的聚合术语中,最好坚持所呈现的数据模式,而不是像这基本上要求的那样,试图将"数据点"表示为"键"。但从这样的样本中无法确定真正的预期用途

使用MongoDB 4.4(未检查以前的版本):

db.coll.aggregate($project: {
  $arrayToObject:
      {$map:
        {
          input: "$arrayToParse",
          as: "this",
          in: {
            "k":"$$this.field",
            "v":"$$this.value"
          }
        }
      }
    }
)

相关内容

  • 没有找到相关文章

最新更新