Toán tử $lookup thực hiện left outer join với collection khác. Khi trường khóa ngoại là **mảng ObjectId**, dùng pipeline con với $match và $in.
Tạo collection chính (demo395):
> db.demo395.insertOne({Name:"Chris"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e782317aa3ef9ab8ab207") }
> db.demo395.insertOne({Name:"David"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e782317aa3ef9ab8ab208") }
Tạo collection tham chiếu (demo396) chứa mảng ObjectId:
> db.demo396.insertOne({
"details" : [
ObjectId("5e5e782317aa3ef9ab8ab207"),
ObjectId("5e5e782317aa3ef9ab8ab208")
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e5e787817aa3ef9ab8ab209") }
Xem dữ liệu:
> db.demo395.find();
> db.demo396.find();$lookup với pipeline để join mảng ObjectId:
> db.demo396.aggregate([ { "$lookup": { "from": "demo395", "let": { "details": "$details" }, "pipeline": [ { "$match": { "$expr": { "$in": [ "$_id", "$$details" ] } } } ], "as": "output" }} ])Kết quả (có mảng output chứa tài liệu join được):
Giải thích:
let: định nghĩa biếndetailstừ trường mảng ObjectIdpipeline: pipeline con chạy trên collectionfrom$match+$expr+$in: lọc tài liệu có _id nằm trong mảng$$detailsas: tên trường chứa kết quả join (mảng)
Cách này linh hoạt hơn $lookup đơn giản (localField/foreignField) khi khóa ngoại là mảng.