Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MongoDB

Triển khai truy vấn tương tự MySQL UNION với MongoDB

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

Lưu ý hiệu suất $lookup

  • Tạo index trên foreignField (No) ở collection right
  • Dùng pipeline trong $lookup để filter sớm (MongoDB 3.6+)
  • Tránh $lookup trên collection lớn không index
CáchMongoDB OperatorSQL Tương đươngGhi chú
Inner Join$lookup + $unwindINNER JOINChỉ cặp khớp
Left Join$lookup (không unwind)LEFT JOINGiữ tất cả left
Union All$unionWith (4.4+)UNION ALLGộp tất cả, giữ trùng
Union Distinct$unionWith + $groupUNIONGộp + distinct