我有MongoDB集合,文档如下:

{"name": "person1", "parents": [
    {"relationship": "father", "name": "father1", "age": 40},
    {"relationship": "mother", "name": "mother1", "age": 42}
]}

{"name": "person2", "parents": [
    {"relationship": "father", "name": "father2", "age": 50},
    {"relationship": "mother", "name": "mother2", "age": 45}
]}

我正在try 将文档展平,如下所示:

{"name": "person1",  "father_name": "father1", "father_age": 40, "mother_name": "mother1", "mother_age": 42}
{"name": "person2",  "father_name": "father2", "father_age": 50, "mother_name": "mother2", "mother_age": 45}

基本上,我希望从parents个数组的每个元素(对象)中获取某些字段,并将它们作为输出文档中的新字段.我怎样才能做到这一点呢?

我编写了如下聚合管道:

[
    {
      $project: {
        _id: 0,
        name: 1,
        father_name: {
          $cond: {
            if: {
              $eq: ["$parents.relationship", "father"],
            },
            then: "$parents.name",
            else: null,
          },
        },
        father_age: {
          $cond: {
            if: {
              $eq: ["$parents.relationship", "father"],
            },
            then: "$parents.age",
            else: null,
          },
        },
        mother_name: {
          $cond: {
            if: {
              $eq: ["$parents.relationship", "mother"],
            },
            then: "$parents.name",
            else: null,
          },
        },
        mother_age: {
          $cond: {
            if: {
              $eq: ["$parents.relationship", "mother"],
            },
            then: "$parents.age",
            else: null,
          },
        },
      },
    },
  ]

但它的输出如下所示,并不像预期的那样:

{
  "name": "person1",
  "father_name": null,
  "father_age": null,
  "mother_name": null,
  "mother_age": null
}

推荐答案

通用解决方案的一个选项是:

db.collection.aggregate([
  {$set: {
      parents: {$map: {
          input: "$parents",
          as: "i",
          in: {$arrayToObject: {$reduce: {
                input: {$objectToArray: "$$i"},
                initialValue: [],
                in: {$concatArrays: [
                    "$$value",
                    {$cond: [
                        {$ne: ["$$this.k", "relationship"]},
                        [
                          {k: {$concat: ["$$i.relationship", "_", "$$this.k"]},
                           v: "$$this.v"}
                        ],
                        []
                    ]}
                ]}
            }}}
      }}
  }},
  {$replaceRoot: {
      newRoot: {$mergeObjects: [
          "$$ROOT",
          {$reduce: {
              input: "$parents",
              initialValue: {},
              in: {$mergeObjects: ["$$value", "$$this"]}
          }}
      ]}
  }},
  {$unset: "parents"}
])

看看它在playground example号公路上是如何工作的

*通用解决方案支持添加字段或关系类型,无需添加任何阶段

Mongodb相关问答推荐

如何拉平mongo DB中的对象并在根目录中保存时有条件地重命名字段?

执行聚合以消除重复并获得唯一计数

MongoDB DB参考返回null值

随着时间的推移在 mongodb 中获得

判断对象数组中的值是否存在golang

更新文档中的数组时,如何在 MongoDB 和 C# 中使用 $push 更新修饰符

Mongodb:查询嵌套在数组中的json对象

如何知道 MongoDB 集合大小?

django 和 mongodb 是否使迁移成为过go ?

在 Mongo 中存储嵌套类别的最有效方法?

无法连接到远程 mongodb 服务器

如何获取 Mongoid 文档的所有字段名称?

在 Postgres JSON 数组中查询

如何使用 mgo 和 Go 查询 MongoDB 的日期范围?

Mongodb:为什么 show dbs 不显示我的数据库?

MongoDB:如何在 100 个集合中找到 10 个随机文档?

如何防止MongoDB在查找文档时返回对象ID?

处理Mongodb连接的正确方法是什么?

用 MongoDB 中的属性表示多对多关系的最佳模型

MongoDb - 利用多 CPU 服务器进行写入繁重的应用程序