【问题标题】:How to get ids of parents based on deeply nested sub document?如何根据深度嵌套的子文档获取父母的ID?
【发布时间】:2020-04-21 07:49:39
【问题描述】:

这个问题是旧问题的延续:Parent.save() not working when sub document / deeply nested document is modified

假设我有如下文件:

{
    "apiCallCount": 1,
    "_id": "5e0da052b4b3fe5188602e11",
    "email": "abc@def.net",
    "password": "123123",
    "userName": "username",
    "companyName": "companyName",
    "apiKey": "apiKey",
    "solutionType": "solutionType",
    "parentCompany": "parentCompany",
    "buildings": [
        {
            "gateways": [
                {
                    "devices": [
                        {
                            "_id": "5e0da052b4b3fe5188602e15",
                            "serialNumber": "serialNumber 1",
                            "area": "area",
                            "connectionStatus": 0,
                            "gatewayKey": "gatewayKey",
                            "applicationNumber": 11,
                            "firmwareVersion": "firmwareVersion",
                            "needsAttention": true,
                            "verificationCode": "123456",
                            "patientRiskStatus": "patientRiskStatus",
                            "patientFirstName": "UPDATED!!!",
                            "patientLastName": "patientLastName",
                            "createdAt": "2020-01-02T07:48:34.287Z",
                            "updatedAt": "2020-01-02T07:48:34.287Z"
                        },
                        {
                            "_id": "5e0da052b4b3fe5188602e14",
                            "serialNumber": "serialNumber 2",
                            "area": "area",
                            "connectionStatus": 0,
                            "gatewayKey": "gatewayKey",
                            "applicationNumber": 22,
                            "firmwareVersion": "firmwareVersion",
                            "needsAttention": true,
                            "verificationCode": "987654",
                            "patientRiskStatus": "patientRiskStatus",
                            "patientFirstName": "patientFirstName",
                            "patientLastName": "patientLastName",
                            "createdAt": "2020-01-02T07:48:34.288Z",
                            "updatedAt": "2020-01-02T07:48:34.288Z"
                        }
                    ],
                    "_id": "5e0da052b4b3fe5188602e13",
                    "gatewayName": "gatewayName 1",
                    "gatewayKey": "gatewayKey",
                    "suite": "suite",
                    "createdAt": "2020-01-02T07:48:34.288Z",
                    "updatedAt": "2020-01-02T07:48:34.288Z"
                }
            ],
            "_id": "5e0da052b4b3fe5188602e12",
            "buildingName": "buildingName 1",
            "address": "address",
            "suite": "suite",
            "floor": "floor",
            "timeZone": "String",
            "createdAt": "2020-01-02T07:48:34.288Z",
            "updatedAt": "2020-01-02T07:48:34.288Z"
        }
    ],
    "createdAt": "2020-01-02T07:48:34.289Z",
    "updatedAt": "2020-01-02T09:10:25.200Z",
    "__v": 0
}

我能够通过文档挖掘并能够使用“verificationCode”获取设备子文档:“123456”

现在我想获取此设备的 gatewayID(上一级)和 buildingID(上一级)。

目前我有这样的电话: 我正在尝试基于深度嵌套的子文档更新父文档。

我通过 accountId 和验证码获取子文档,如下所示。 然后需要更新父级。

在下面的示例中,我放置了我需要获得运行时间的硬编码 ID。

if (newlySavedUser) {
            try {
                let result = await Account.findByIdAndUpdate(
                    accountId,
                    {
                        $set: {
                            "buildings.$[building].gateways.$[gateway].devices.$[device].patientFirstName": "userName",
                            "buildings.$[building].gateways.$[gateway].devices.$[device].patientLastName": "userName1"
                        }
                    },
                    {
                        arrayFilters: [

                            { "building._id": ObjectId("5d254bb179584ebcbb68b712") },  /// <----  I want to get this buildingId
                            { "gateway._id": ObjectId("5d254b64ba574040d9632ada") }, /// <----  I want to get this gatewayId
                            { "device.verificationCode": "4144" } /// <-- based on this verificationCode
                        ],
                        new: true
                    }
                );

                if (!result) return res.status(404);
                console.log(result)
                //res.send(result);
            } catch (err) {
                console.log(err);
                res.status(500).send("Something went wrong");
            }
        }

正在尝试聚合的“tom slabbaert”解决方案。

Account.aggregate([
                {
                    $unwind: "$buildings"
                },
                {
                    $unwind: "$gateways"
                },
                {
                    $match: {
                        "buildings.gateways.devices.verificationCode": "4144"
                    }
                },
                {
                    $project: {
                        buildingID: "$buildings._id",
                        gatewayID: "$gateways._id",
                    }
                }
            ]).exec((err, result)=>{
                console.log("result", result)
                if(err) throw err;
            });

感谢您的帮助。

【问题讨论】:

    标签: mongodb mongoose mongodb-query


    【解决方案1】:

    你可以使用这个 3 级 $unwind 聚合,然后匹配你想要的文档:

    db.collection.aggregate([
      {
        $unwind: "$buildings"
      },
      {
        $unwind: "$buildings.gateways"
      },
      {
        $unwind: "$buildings.gateways.devices"
      },
      {
        $match: {
          "buildings._id": "5e0da052b4b3fe5188602e12",
          "buildings.gateways._id": "5e0da052b4b3fe5188602e13",
          "buildings.gateways.devices.verificationCode": "123456"
        }
      }
    ])
    

    这将为您提供以下结果:

    [
      {
        "__v": 0,
        "_id": "5e0da052b4b3fe5188602e11",
        "apiCallCount": 1,
        "apiKey": "apiKey",
        "buildings": {
          "_id": "5e0da052b4b3fe5188602e12",
          "address": "address",
          "buildingName": "buildingName 1",
          "createdAt": "2020-01-02T07:48:34.288Z",
          "floor": "floor",
          "gateways": {
            "_id": "5e0da052b4b3fe5188602e13",
            "createdAt": "2020-01-02T07:48:34.288Z",
            "devices": {
              "_id": "5e0da052b4b3fe5188602e15",
              "applicationNumber": 11,
              "area": "area",
              "connectionStatus": 0,
              "createdAt": "2020-01-02T07:48:34.287Z",
              "firmwareVersion": "firmwareVersion",
              "gatewayKey": "gatewayKey",
              "needsAttention": true,
              "patientFirstName": "UPDATED!!!",
              "patientLastName": "patientLastName",
              "patientRiskStatus": "patientRiskStatus",
              "serialNumber": "serialNumber 1",
              "updatedAt": "2020-01-02T07:48:34.287Z",
              "verificationCode": "123456"
            },
            "gatewayKey": "gatewayKey",
            "gatewayName": "gatewayName 1",
            "suite": "suite",
            "updatedAt": "2020-01-02T07:48:34.288Z"
          },
          "suite": "suite",
          "timeZone": "String",
          "updatedAt": "2020-01-02T07:48:34.288Z"
        },
        "companyName": "companyName",
        "createdAt": "2020-01-02T07:48:34.289Z",
        "email": "abc@def.net",
        "parentCompany": "parentCompany",
        "password": "123123",
        "solutionType": "solutionType",
        "updatedAt": "2020-01-02T09:10:25.200Z",
        "userName": "username"
      }
    ]
    

    Mongoplayground

    【讨论】:

      【解决方案2】:

      一个简单的聚合就足够了:

          db.collection.aggregate([
              {
                  $unwind: "$buildings"
              },
              {
                  $unwind: "$buildings.gateways"
              },
              {
                  $match: {
                      "buildings.
      gateways.devices.verificationCode": "123456"
                  }
              },
              {
                  $project: {
                      buildingID: "$buildings._id",
                      gatewayID: "$gateways._id",
                  }
              }
          ])
      

      如果可能出现重复,您可以在 buildingID 上$group 来避免这种情况。

      【讨论】:

      • 非常感谢您的努力。抱歉,如果我没有提供足够的信息,但我用更多细节更新了我的问题.. 根据我从@SuleymanSah 的上一个问题得到的解决方案
      • 您不能对查询投影中的嵌套字段进行任何操作,因此您需要在代码中使用您获得的结果进行操作,或者在之后运行另一个查询。
      • 好的,如果我在下面尝试 - console.log 返回空。请在底部检查我的更新问题。我引用了你的名字。
      • 我在比赛阶段错误地写了“gatewqys.xxx”而不是“buildings.gateways.xxx”,已修复。
      • 感谢您的贡献。它仍然给了我空数组结果。 @SuleymanSah 的解决方案对我有用。
      猜你喜欢
      • 1970-01-01
      • 2014-06-10
      • 2013-08-12
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      相关资源
      最近更新 更多