Mô phỏng UNION ALL hai collection với $lookup + $group
MongoDB không có UNION như SQL. Dùng $lookup (left join) + $unwind + $group để gộp dữ liệu từ 2 collection theo khóa chung.
1. Collection demo486 (Amount)
> db.demo486.insertOne({ _id: 1, Amount: 30, No: 4 });
> db.demo486.insertOne({ _id: 2, Amount: 40, No: 2 });
> db.demo486.insertOne({ _id: 3, Amount: 60, No: 6 });
2. Collection demo487 (Price)
> db.demo487.insertOne({ _id: 1, Price: 10, No: 4 });
> db.demo487.insertOne({ _id: 2, Price: 80, No: 9 });
> db.demo487.insertOne({ _id: 3, Price: 20, No: 6 });
3. Pipeline "UNION" theo field No
> db.getCollection('demo486').aggregate([
{
$lookup: {
from: "demo487",
localField: "No",
foreignField: "No",
as: "demo487"
}
},
{ $unwind: "$demo487" }, // Chỉ giữ cặp khớp (INNER JOIN)
{
$group: {
_id: { No: "$No" },
TotalValue: { $sum: { $add: ["$Amount", "$demo487.Price"] } }
}
},
{ $sort: { "_id.No": 1 } },
{
$project: {
No: "$_id.No",
TotalValue: 1,
_id: 0
}
}
]);
4. Kết quả
{ "TotalValue": 40, "No": 4 } // 30 + 10
{ "TotalValue": 80, "No": 6 } // 60 + 20
// Lưu ý: No=2 (Amount=40) và No=9 (Price=80) không khớp → bị loại do $unwind
Giải thích: Đây là INNER JOIN, không phải UNION
- UNION ALL: Gộp tất cả hàng từ 2 bảng (giữ trùng)
- UNION: Gộp + distinct
- Ví dụ này: JOIN trên No, tính tổng Amount+Price → chỉ giữ cặp khớp
Cách làm UNION ALL thực sự (MongoDB 4.4+): $unionWith
db.demo486.aggregate([
{ $unionWith: "demo487" }, // Gộp tất cả doc từ demo487
{ $group: { _id: "$No", TotalValue: { $sum: { $add: ["$Amount", "$Price"] } } } },
{ $project: { No: "$_id", TotalValue: 1, _id: 0 } }
]);
// Kết quả: No=2 (40), No=4 (40), No=6 (80), No=9 (80)
So sánh các cách gộp dữ liệu
| Cách | MongoDB Operator | SQL Tương đương | Ghi chú |
|---|---|---|---|
| Inner Join | $lookup + $unwind | INNER JOIN | Chỉ cặp khớp |
| Left Join | $lookup (không unwind) | LEFT JOIN | Giữ tất cả left |
| Union All | $unionWith (4.4+) | UNION ALL | Gộp tất cả, giữ trùng |
| Union Distinct | $unionWith + $group | UNION | Gộp + distinct |