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

Chiếu trường (Project Field) trong MongoDB Aggregation

Stage $project trong MongoDB Aggregation Pipeline dùng để **chọn, đổi tên, tính toán, restructure** trường đầu ra. Nó tương tự projection trong find() nhưng mạnh hơn rất nhiều: cho phép biểu thức, điều kiện, mảng, object lồng.

1. Tạo dữ liệu: MarksInformation có cấu trúc khác nhau (Marks1-3 vs Score1-2)

> db.demo439.insertOne({ "Name": "Chris", "MarksInformation": { "Marks1": 67, "Marks2": 45, "Marks3": 78 } });
> db.demo439.insertOne({ "Name": "David", "MarksInformation": { "Marks1": 50, "Marks2": 57, "Marks3": 68 } });
> db.demo439.insertOne({ "Name": "Bob", "MarksInformation": { "Score1": 65, "Score2": 71 } });

2. $project: Chuẩn hóa output thành Marks1, Marks2, Marks3 (fallback Score -> Marks)

> db.demo439.aggregate([
    {
        $project: {
            "Name": 1,
            "Marks1": {
                $cond: [
                    { $eq: [{ $ifNull: ["$MarksInformation.Marks1", 0] }, 0] },
                    { $ifNull: ["$MarksInformation.Score1", 0] },
                    "$MarksInformation.Marks1"
                ]
            },
            "Marks2": {
                $cond: [
                    { $eq: [{ $ifNull: ["$MarksInformation.Marks2", 0] }, 0] },
                    { $ifNull: ["$MarksInformation.Score2", 0] },
                    "$MarksInformation.Marks2"
                ]
            },
            "Marks3": {
                $cond: [
                    { $eq: [{ $ifNull: ["$MarksInformation.Marks3", 0] }, 0] },
                    { $ifNull: ["$MarksInformation.Score3", 0] },
                    "$MarksInformation.Marks3"
                ]
            }
        }
    }
]);

3. Kết quả: Cấu trúc thống nhất Marks1, Marks2, Marks3

{ "_id": ObjectId("..."), "Name": "Chris", "Marks1": 67, "Marks2": 45, "Marks3": 78 }
{ "_id": ObjectId("..."), "Name": "David", "Marks1": 50, "Marks2": 57, "Marks3": 68 }
{ "_id": ObjectId("..."), "Name": "Bob", "Marks1": 65, "Marks2": 71, "Marks3": 0 }

Giải thích logic fallback:

  • $ifNull: [field, default]: Trả về field nếu không null/missing, ngược lại default.
  • Kiểm tra Marks1 có tồn tại và ≠ 0 không ($eq: [..., 0]). Nếu thiếu/bằng 0 -> fallback sang Score1.
  • Bob không có Marks3, Score3 -> fallback 0.

Cách hiện đại (MongoDB 5.0+): Dù $coalesce

Marks1: { $coalesce: ["$MarksInformation.Marks1", "$MarksInformation.Score1", 0] }

$coalesce trả về giá trị đầu tiên non-null trong danh sách - ngắn gọn, dễ đọc hơn $cond + $ifNull lồng nhau.