如何根据条件选择进行查找?

时间:2019-08-04 11:43:39

标签: mongodb aggregation-framework lookup

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

collection1

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

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

这是我的收藏2

collection2

 "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"
      }
    ]
  }
]

1 个答案:

答案 0 :(得分:1)

是的,您可以为$lookup pipeline定义自己的匹配条件,但是由于您的结构是深度嵌套的,因此您需要在运行sub_menus之前使用$reduce展平$lookup 。将所有匹配的项目带到任何子菜单后,您可以将$ map和$ filter一起使用,以将其放入sub_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 Playground