如何根据条件选择进行查找?
How can I do a lookup based on conditional selection?
我有 2 个 collection 基于 collection1 我需要从 collection2
中获取
collection1
[
{
"_id": ObjectId("5ce7454f77af2d1143f84c38"),
"menu_name": "mainmenu1",
"sub_menus": [
{
"name": "submenu1",
"project": [
"All"
]
},
{
"name": "submenu2",
"project": [
"p2"
]
}
]
}
]
根据项目领域我需要获取记录。如果项目字段是 "All",我需要获取该子菜单下的所有项目。如果它是特定项目,则只有我需要获取的那些项目。
这是我的 collection2
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"
}
]
}
]
是的,您可以在 运行 您的 $lookup
之前为 $lookup pipeline but since your structure is deeply nested you need to flatten your sub_menus
using $reduce 定义自己的匹配条件。一旦你将所有匹配到任何子菜单的项目都可以使用 $map 和 $filter 将它们放入 releval 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
}
}
])
我有 2 个 collection 基于 collection1 我需要从 collection2
中获取collection1
[
{
"_id": ObjectId("5ce7454f77af2d1143f84c38"),
"menu_name": "mainmenu1",
"sub_menus": [
{
"name": "submenu1",
"project": [
"All"
]
},
{
"name": "submenu2",
"project": [
"p2"
]
}
]
}
]
根据项目领域我需要获取记录。如果项目字段是 "All",我需要获取该子菜单下的所有项目。如果它是特定项目,则只有我需要获取的那些项目。
这是我的 collection2
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"
}
]
}
]
是的,您可以在 运行 您的 $lookup
之前为 $lookup pipeline but since your structure is deeply nested you need to flatten your sub_menus
using $reduce 定义自己的匹配条件。一旦你将所有匹配到任何子菜单的项目都可以使用 $map 和 $filter 将它们放入 releval 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
}
}
])