首页 > 解决方案 > 如何根据条件选择进行查找?

问题描述

我有 2 个基于 collection1 的集合,我需要从 collection2 中获取

集合1

 [
    {
      "_id": ObjectId("5ce7454f77af2d1143f84c38"),
      "menu_name": "mainmenu1",
      "sub_menus": [
        {
          "name": "submenu1",
          "project": [
            "All"
          ]
        },
        {
          "name": "submenu2",
          "project": [
            "p2"
          ]
        }
      ]
    }
  ]

根据项目字段,我需要获取记录。如果项目字段是“全部”,我需要获取该子菜单下的所有项目。如果它是特定项目,则只有我需要获取的那些项目。

这是我的收藏2

集合2

 "project": [
{
  "project_name": "p1",
  "sub_menus": "submenu1",

},
{
  "project_name": "p2",
  "sub_menus": "submenu2",

}
{
  "project_name": "p2",
  "sub_menus": "submenu1",

},
{
  "project_name": "p3",
  "sub_menus": "submenu2",

}
{
  "project_name": "p3",
  "sub_menus": "submenu1",

},
{
  "project_name": "p4",
  "sub_menus": "submenu2",

}

]

https://mongoplayground.net/p/qH9fuJorq6z。我可以进行条件查找吗?

预期结果是

[
  {
    "_id": ObjectId("5ce7454f77af2d1143f84c38"),
    "menu_name": "mainmenu1",
    "sub_menus": [
      {
         "projectData": [
          {
            "project_name": "p1"      
          },
          {
          "project_name": "p2"
          },
          {
          "project_name": "p3"
          }
        ],
        "sub_menu_name": "submenu1"
      },
      {

        "projectData": [
          {
            "project_name": "p2"
          }
        ],
        "sub_menu_name": "submenu2"
      }
    ]
  }
]

标签: mongodbaggregation-frameworklookup

解决方案


是的,您可以为$ lookup 管道定义您自己的匹配条件,但是由于您的结构是深度嵌套的,您需要在运行. 将所有匹配到任何子菜单的项目带入后,您可以使用 $map 和 $filter 将它们放入 releval :sub_menus$lookupsub_menu

db.collection1.aggregate([
    {
        $addFields: {
            sub_menus_flat: {
                $reduce: {
                    input: "$sub_menus",
                    initialValue: [],
                    in: {
                        $concatArrays: [ 
                            "$$value", 
                            { $map: { input: "$$this.project", as: "p", in: { name: "$$this.name", project: "$$p" } } } 
                        ]
                    }
                }
            }
        }
    },
    {
        $lookup: {
            from: "collection2",
            let: { sub_menus_flat: "$sub_menus_flat" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $anyElementTrue: {
                                $map: {
                                    input: "$$sub_menus_flat",
                                    in: {
                                        $and: [
                                            { $eq: [ "$$this.name", "$sub_menus" ] },
                                            { $in: [ "$$this.project", [ "All", "$project_name" ] ] }
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            ],
            as: "projects"
        }
    },
    {
        $project: {
            _id: 1,
            menu_name: 1,
            sub_menus: {
                $map: {
                    input: "$sub_menus",
                    in: {
                        sub_menu_name: "$$this.name",
                        projectData: {
                            $filter: {
                                input: "$projects",
                                as: "p",
                                cond: {
                                    $and: [
                                        { $eq: [ "$$p.sub_menus", "$$this.name" ] }
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $project: {
            "sub_menus.projectData._id": 0,
            "sub_menus.projectData.sub_menus": 0
        }
    }
])

MongoDB游乐场


推荐阅读