MongoDB使用数组遍历3个集合的嵌套查找

时间:2019-08-02 13:34:04

标签: mongodb mongodb-query

我想从三个集合中查找。起点是一个具有数组的集合,在该数组中有一些我想用来查找另一个集合的键。根据该查找的结果,我想进行另一次查找。为了方便起见,我将尝试共享一个Mongo游乐场实例。

这是实例的链接: https://mongoplayground.net/p/4rJflL1UF81

使用此工具,您可以查看mongodb版本以及源集合,查询和实际结果。

我已经尝试了几种方法:

db.SlittingPatterns.aggregate([
  {
    "$lookup": {
      "from": "Orders",
      "localField": "STPO.AUFNR",
      "foreignField": "OrderHead.AUFNR",
      "as": "ORDERS"
    }
  },
  {
    "$lookup": {
      "from": "Materials",
      "localField": "ORDERS.OrderHead.MATNR",
      "foreignField": "MATERIAL.AS_MARA.MATNR",
      "as": "MATERIALS"
    }
  }
])


db.SlittingPatterns.aggregate([
    {
        "$lookup": {
            "from": "Orders",
            "let": {
                "aufnr": "$STPO.AUFNR"
            },
            "pipeline": [
                {
                    "$match": {
                        "$expr": {
                            "$eq": [
                                "$OrderHead.AUFNR",
                                "$$aufnr"
                            ]
                        }
                    }
                },
                {
                    "$lookup": {
                        "from": "Materials",
                        "let": {
                            "matnr": "$OrderHead.MATNR"
                        },
                        "pipeline": [
                            {
                                "$match": {
                                    "$expr": {
                                        "$eq": [
                                            "$MATERIAL.AS_MARA.MATNR",
                                            "$$matnr"
                                        ]
                                    }
                                }
                            }
                        ],
                        "as": "MATERIALS"
                    }
                },
                {
                    "$unwind": "$MATERIALS"
                }
            ],
            "as": "ORDERS"
        }
    },
    {
        "$unwind": "$ORDERS"
    }
])

最后一个灵感来自于这个问题:

$lookup nested array in mongodb

这似乎与我想要的非常接近,但是似乎因为STPO数组中的键位于对象内部,所以它不起作用。如果我切换

"let": {
  "aufnr": "$STPO.AUFNR"
}

使用

"let": {
  "aufnr": "$STKO.RUNNR"
}

正在生成所需的格式,但是它仍然不正确,因为需要从STPO阵列中收集AUFNR。

第一个获取我想要的所有数据,但不是我想要的格式,这将很快出现。我大概只需要在查询中进一步转换此结果,但是目前,我还不知道如何。我也无法展示我在这方面已经尝试过的内容,因为我还没有找到与之相近的所需格式。

这是预期的结果:

[
  {
    "ORDERS": [
      {
        "MATERIALS": [
          {
            "MATERIAL": {
              "AS_MARA": {
                "MATNR": "456"
              }
            },
            "_id": ObjectId("5a934e000102030405000000")
          }
        ],
        "OrderHead": {
          "AUFNR": "123",
          "MATNR": "456"
        },
        "_id": ObjectId("5a934e000102030405000003")
      },
      {
        "MATERIALS": [
          {
            "MATERIAL": {
              "AS_MARA": {
                "MATNR": "654"
              }
            },
            "_id": ObjectId("5a934e000102030405000001")
          }
        ],
        "OrderHead": {
          "AUFNR": "321",
          "MATNR": "654"
        },
        "_id": ObjectId("5a934e000102030405000004")
      }
    ],
    "STKO": {
      "RUNNR": "123"
    },
    "STPO": [
      {
        "AUFNR": "123"
      },
      {
        "AUFNR": "321"
      }
    ],
    "_id": ObjectId("5a934e000102030405000005")
  }
]

1 个答案:

答案 0 :(得分:1)

我们需要首先展开“ STPO”,以将其值查找到另一个集合中。以下查询可以为您提供预期的输出:

db.SlittingPatterns.aggregate([
    {
        $unwind:"$STPO"
    },
    {
        $lookup:{
            "from":"Orders",
            "let":{
                "aufnr":"$STPO.AUFNR"
            },
            "pipeline":[
                {
                    $match:{
                        $expr:{
                            $eq:["$OrderHead.AUFNR","$$aufnr"]
                        }
                    }
                },
                {
                    $lookup:{
                        "from":"Materials",
                        "let":{
                            "matnr":"$OrderHead.MATNR"
                        },
                        "pipeline":[
                            {
                                $match:{
                                    $expr:{
                                        $eq:["$MATERIAL.AS_MARA.MATNR","$$matnr"]
                                    }
                                }
                            }
                        ],
                        "as":"MATERIALS"
                    }
                }
            ],
            "as":"ORDERS"
        }
    },
    {
        $unwind:{
            path: "$ORDERS",
            "preserveNullAndEmptyArrays":true
        }
    },
    {
        $group:{
            "_id":"$_id",
            "STKO":{
                $first:"$STKO"
            },
            "STPO":{
                $push:"$STPO"
            },
            "ORDERS":{
                $push:"$ORDERS"
            }
        }
    }
]).pretty()

输出:

{
    "_id" : ObjectId("5d444745748b0f59369a8040"),
    "STKO" : {
        "RUNNR" : "123"
    },
    "STPO" : [
        {
            "AUFNR" : "123"
        },
        {
            "AUFNR" : "321"
        }
    ],
    "ORDERS" : [
        {
            "_id" : ObjectId("5d444732748b0f59369a803e"),
            "OrderHead" : {
                "AUFNR" : "123",
                "MATNR" : "456"
            },
            "MATERIALS" : [
                {
                    "_id" : ObjectId("5d444718748b0f59369a803b"),
                    "MATERIAL" : {
                        "AS_MARA" : {
                            "MATNR" : "456"
                        }
                    }
                }
            ]
        },
        {
            "_id" : ObjectId("5d444732748b0f59369a803f"),
            "OrderHead" : {
                "AUFNR" : "321",
                "MATNR" : "654"
            },
            "MATERIALS" : [
                {
                    "_id" : ObjectId("5d444718748b0f59369a803c"),
                    "MATERIAL" : {
                        "AS_MARA" : {
                            "MATNR" : "654"
                        }
                    }
                }
            ]
        }
    ]
}