当前位置: 首页 > 知识库问答 >
问题:

Mongodb子文档数组查找到子文档数组

羊丰茂
2023-03-14

我是新来的mongo。我有以下收藏。

文件

{
    "_id" : ObjectId("5eb256c9e519051af2eeb5f7"),
    "name" : "Income",
    "types" : [ 
        {
            "typeId" : ObjectId("5eb257a3e519051af2eeb624"),
            "name" : "W2",
            "tenantId" : null,
            "message" : "",
            "createdOn" : null,
            "createdBy" : 1.0,
            "isActive" : true
        }, 
        {
            "typeId" : ObjectId("5eb257a3e519051af2eeb639"),
            "name" : "Salary Slip",
            "tenantId" : 1,
            "message" : "",
            "createdOn" : null,
            "createdBy" : 1.0,
            "isActive" : true
        }
    ]
}

请求:

{
    "_id" : ObjectId("5eb25d1fe519051af2eeb72d"),
    "employeeId" : 1234,
    "customerId" : 1275,
    "tenantId" : 1,
    "createdOn" : ISODate("2013-10-01T00:00:00.000Z"),
    "loanApplicationId" : 1.0,
    "status" : "requested",
    "message" : "Dear John, please send following documents.",
    "documents" : [ 
        {
            "typeId" : null,
            "displayName" : "W2 2016",
            "message" : "please upload salary slip for year 2016",
            "status" : "requested",
            "files" : []
        }, 
        {
            "typeId" : ObjectId("5eb257a3e519051af2eeb624"),
            "displayName" : "W2 2016",
            "message" : "please upload salary slip for year 2016",
            "status" : "requested",
            "files" : []
        }
    ]
}

文档集合中的typeId是文档类型的id,其中请求中的typeId是也可以为空的外部字段。如何获得以下输出。

{
    "_id" : ObjectId("5eb25d1fe519051af2eeb72d"),
    "employeeId" : 1234,
    "customerId" : 1275,
    "tenantId" : 1,
    "createdOn" : ISODate("2013-10-01T00:00:00.000Z"),
    "loanApplicationId" : 1.0,
    "status" : "requested",
    "message" : "Dear John, please send following documents.",
    "documents" : [ 
        {
            "typeId" : null,
            "typeInfo": null,
            "displayName" : "W2 2016",
            "message" : "please upload salary slip for year 2016",
            "status" : "requested",
            "files" : []
        }, 
        {
            "typeId" : ObjectId("5eb257a3e519051af2eeb624"),
            "typeInfo": {
            "name": "W2" 
            },
            "displayName" : "W2 2016",
            "message" : "please upload salary slip for year 2016",
            "status" : "requested",
            "files" : []
        }
    ]
}

共有2个答案

屈晨
2023-03-14

使用默认的$查找语法,可以使用原子/数组值进行联接,并将结果存储在tmp变量中。在下一步中,我们迭代文档字段,并在tmp中找到具有相同类型ID的变量项。

注意:如果您需要的字段多于名称,只需更改为类型信息:“$$this”}。

试试这个:

db.Requests.aggregate([
  {
    $lookup: {
      from: "Documents",
      localField: "documents.typeId",
      foreignField: "types.typeId",
      as: "tmp"
    }
  },
  {
    $addFields: {
      tmp: "$$REMOVE",
      documents: {
        $map: {
          input: "$documents",
          as: "doc",
          in: {
            $mergeObjects: [
              "$$doc",
              {
                $reduce: {
                  input: {
                    $reduce: {
                      input: "$tmp.types",
                      initialValue: [],
                      in: {
                        $concatArrays: [
                          "$$value",
                          "$$this"
                        ]
                      }
                    }
                  },
                  initialValue: {},
                  in: {
                    $cond: [
                      {
                        $eq: [
                          "$$this.typeId",
                          "$$doc.typeId"
                        ]
                      },
                      {
                        typeInfo: {
                          name: "$$this.name"
                        }
                      },
                      "$$value"
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

MongoPlayground

姜凯风
2023-03-14

我喜欢解决这个问题,这是一个棘手、漫长而复杂的问题。嗯,我也是初学者,所以我使用了所有的基本概念。您可以尝试以下代码:

db.request.aggregate([
  {
    $unwind: "$documents"
  },
  {
    $lookup: {
      from: "document",
      let: {
        req_typeId: "$documents.typeId"
      },
      pipeline: [
        {
          $unwind: "$types"
        },
        {
          $match: {
            $expr: {
              $eq: [
                "$$req_typeId",
                "$types.typeId"
              ]
            }
          }
        }
      ],
      as: "documents.example"
    }
  },
  {
    $unwind: {
      path: "$documents.example",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $group: {
      _id: "$_id",
      employeeId: {
        $first: "$employeeId"
      },
      customerId: {
        $first: "$customerId"
      },
      tenantId: {
        $first: "$tenantId"
      },
      createdOn: {
        $first: "$createdOn"
      },
      loanApplicationId: {
        $first: "$loanApplicationId"
      },
      status: {
        $first: "$status"
      },
      message: {
        $first: "$message"
      },
      documents: {
        $push: {
          typeId: "$documents.typeId",
          typeInfo: {
            $cond: [
              {
                $eq: [
                  "$documents.example",
                  undefined
                ]
              },
              null,
              {
                name: "$documents.example.types.name"
              }
            ]
          },
          displayName: "$documents.displayName",
          message: "$documents.message",
          status: "$documents.status",
          files: "$documents.files"
        }
      }
    }
  }
])

如果您在任何时候遇到困难,我已经提供了MongoPlayGround链接,您可以在这里一步一步地执行聚合管道的查询,否则请联系我。这是一个很长的问题,需要时间才能理解。同时,我会尽量缩小它。如果我得到什么,我会在这里更新。

编辑:

我将查询缩短了近50%(按行计算)。这是我以前的方法的链接

 类似资料:
  • 问题内容: 我正在使用MongoDB数据库,该数据库的收集模型包括 班级 , 学生 , 学科 和[学术] 表现 。以下是基于猫鼬的架构和模型: 该集合的文件是最复杂的地段; 示例文档为: 我能够使用以下代码检索现有的班级文档并将其添加到分数中: 但是,如何添加/更新/删除该特定学生的成绩?我需要能够通过以下方式与集合进行交互: 检索所有学生或特定学生的分数(检索数组中的特定元素) 为特定主题添加/

  • 我有一份这样的文件: 我想通过将其与数量字段(2*800)相乘来更新价格字段,其中的结果将更新/分配给价格。(对于本例,价格更新为1600)。 更新后的文档: 我的选择查询如下: 我怎样才能做到这一点?

  • 问题内容: 我正在尝试使用Spring查询Mongo存储库并过滤数组子文档。我已经参考过如何使用mongodb过滤子文档中的数组,但是想知道是否有更合适的方法或Java结构化方法来使用Spring。 我当前正在使用速记存储库接口符号,但是我正在获取未过滤数组的完整文档。 PersonRepository.java 人.java 地址.java 样本输入 预期产量 实际产量 问题答案: 好吧,在Sp

  • b)“Units”字段包含带有“period”字段的子文档(日期对象数组),其中给定的日期位于数组中的第一和第二元素之间。 数据结构如下所示: 我尝试使用.find()和.aggregate()的各种组合,例如在periol数组上使用$project和$filter,在unit._id上使用$elemmatch之后使用$elemmatch,但是没有用--我得到了诸如“不能在数组上使用$filter

  • 我有一份这样的文件 上面的文档可以这样概括如下,便于理解。 我需要增加nums子文档中数量的值,该值位于产品子文档中,基于其\u id。 这是我迄今为止所尝试的,但它不起作用,因为我不知道如何捕获nums对象内的\u id,以便更新子子文档数组中的特定对象。 我怎样才能做到这一点?

  • 将mongodb与pymongo一起使用,我有以下文档: 我想更新示例子文档(这是一个数组元素,因为可能有多个示例)。我有以下代码,但它不工作... 谁能告诉我这个有什么问题吗?