Về cơ bản, bạn cần phải $unwind
mảng đầu tiên. MongoDB chưa thể hoạt động với thuộc tính "bên trong" của một đối tượng trong một mảng làm nguồn cho $lookup
.
Ngoài ra, để hiệu quả, chúng ta thực sự nên sử dụng $concatArrays
trước tiên để "tham gia" nguồn mảng, sau đó chỉ thực hiện một $lookup
hoạt động:
Project.aggregate([
{ "$match": { "project_id": projectId} },
{ "$project": {
"project_id": 1,
"updated_at": 1,
"created_at": 1,
"owner": 1,
"name": 1,
"combined": {
"$concatArrays": [
{ "$map": {
"input": {
"$filter": {
"input": "$uploaded_files",
"as": "uf",
"cond": { "$eq": ["$$uf.upload_id", uploadId ] }
}
},
"as": "uf",
"in": {
"$arrayToObject": {
"$concatArrays": [
{ "$objectToArray": "$$uf" },
[{ "k": "type", "v": "uploaded_files" }]
]
}
}
}},
{ "$map": {
"input": {
"$filter": {
"input": "$file_history",
"as": "fh",
"cond": { "$eq": ["$$fh.upload_id", uploadId ] }
}
},
"as": "fh",
"in": {
"$arrayToObject": {
"$concatArrays": [
{ "$objectToArray": "$$fh" },
[{ "k": "type", "v": "file_history" }]
]
}
}
}}
]
}
}},
{ "$unwind": "$combined" },
{ "$lookup": {
"from": "files",
"localField": "combined.file",
"foreignField": "_id",
"as": "combined.file"
}},
{ "$unwind": "$combined.file" },
{ "$lookup": {
"from": "users",
"localField": "owner",
"foreignField": "_id",
"as": "owner"
}},
{ "$unwind": "$owner" },
{ "$group": {
"_id": "$_id",
"project_id": { "$first": "$project_id" },
"updated_at": { "$first": "$updated_at" },
"created_at": { "$first": "$created_at" },
"owner": { "$first": "$owner" },
"name": { "$first": "$name" },
"combined": { "$push": "$combined" }
}},
{ "$project": {
"project_id": 1,
"updated_at": 1,
"created_at": 1,
"owner": 1,
"name": 1,
"uploaded_files": {
"$filter": {
"input": "$combined",
"as": "cf",
"cond": { "$eq": [ "$$cf.type", "uploaded_files" ] }
}
},
"file_history": {
"$filter": {
"input": "$combined",
"as": "cf",
"cond": { "$eq": [ "$$cf.type", "file_history" ] }
}
}
}}
])
Tóm lại
-
Tập hợp hai mảng lại với nhau trên nguồn và gắn thẻ chúng, sau đó
$unwind
đầu tiên -
$group
tài liệu trở lại cùng với một mảng. -
$filter
bằng trường "tên thẻ" hoặc "loại" mà chúng tôi đã thêm để "phân tách" các mảng.
Bạn có thể làm theo cùng một loại quy trình chỉ đơn giản bằng cách sử dụng $unwind
trên mỗi mảng, sau đó thực hiện "nối" và nhóm lại với nhau. Nhưng thực sự điều đó cần nhiều bước hơn, thay vì chỉ đơn giản là "kết hợp" ngay từ đầu.