在MongoDB中展平嵌套对象并重命名

Ayu*_*wal 1 mongodb mongodb-query aggregation-framework

假设我有这样的文件

{
    "id" : "1415166669",
    "color" : {
        "14" : "Silver"
    },
    "name":"Random Name"
}
Run Code Online (Sandbox Code Playgroud)

内部颜色键可以更改的位置,即"下一个文档"可能如下所示

{
    "id" : "1415126969",
    "color" : {
        "11" : "Gold"
    },
    "name":"Random Name 2"
}
Run Code Online (Sandbox Code Playgroud)

我想展平并重命名它们,以便我的文档具有如下相似的结构:

{
    "id" : "1415126969",
    "color"  : "Gold"
    "name":"Random Name 2"
}
Run Code Online (Sandbox Code Playgroud)

{
    "id" : "1415166669",
    "color" : "Silver"
    "name":"Random Name"
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用聚合管道但我不确定如何继续进行.任何人都可以建议使用Robomongo的方式,这也很好.

Nei*_*unn 6

我会为此运行一个简单的JavaScript循环,因为它将非常快速且易于编码.它也可以应用于同一个集合:

var ops = [];

db.collection.find().forEach(function(doc) {
  let color;
  Object.keys(doc.color).forEach(function(key) {
    color = doc.color[key];
  });
  ops = [
    ...ops,
    { "updateOne": {
      "filter": { "_id": doc._id },
      "update": { "$set": { "color": color } }
    }}
  ];
  if ( ops.length >= 500 ) {
    db.collection.bulkWrite(ops);
     ops = [];
  }
})

if ( ops.length > 0 ) {
  db.collection.bulkWrite(ops);
   ops = [];
}
Run Code Online (Sandbox Code Playgroud)

因此,您基本上遍历对象的"键"并获取值,稍后我们将回写到文档中 $set

或者,从MongoDB 3.4开始,您可以使用聚合语句$objectToArray来访问密钥.但是你真的只应该在集合有数百万个文档的情况下这样做.要求$out意味着结果是新的集合,而不是当前正在更新的集合:

db.collecion.aggregate([
  { "$addFields": {
    "color": {
     "$arrayElemAt": [
       { "$map": {
         "input": { "$objectToArray": "$color" },
         "as": "c",
         "in": "$$c.v"
       }},
       0
     ]
    }
  }},
  { "$out": "newcollection" }
])
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为$objectToArray你的结构如下:

"color": { "11": "Gold" }
Run Code Online (Sandbox Code Playgroud)

进入:

"color": [{ "k": "11", "v": "Gold" }]
Run Code Online (Sandbox Code Playgroud)

因此,我们可以使用$map运算符来提取"color.v"路径值并将$arrayElemAt其转换为奇异值而不是数组.

一般来说,这种转换对于聚合管道语句来说要比通过在代码中操作文档结构然后写回目标集合而实现的更复杂.


鉴于现有文件:

{
        "_id" : ObjectId("59389951fc04695e84e7f4ae"),
        "id" : "1415166669",
        "color" : {
                "14" : "Silver"
        },
        "name" : "Random Name"
}
{
        "_id" : ObjectId("59389a75fc04695e84e7f4af"),
        "id" : "1415126969",
        "color" : {
                "11" : "Gold"
        },
        "name" : "Random Name 2"
}
Run Code Online (Sandbox Code Playgroud)

两种方法的输出是:

{
        "_id" : ObjectId("59389951fc04695e84e7f4ae"),
        "id" : "1415166669",
        "color" : "Silver",
        "name" : "Random Name"
}
{
        "_id" : ObjectId("59389a75fc04695e84e7f4af"),
        "id" : "1415126969",
        "color" : "Gold",
        "name" : "Random Name 2"
}
Run Code Online (Sandbox Code Playgroud)