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

Kết hợp phần tử duy nhất (unique) từ nhiều mảng trong MongoDB

Để gộp các mảng từ nhiều tài liệu/trường khác nhau và lấy **các giá trị duy nhất (unique)**, MongoDB Aggregation cung cấp các toán tử Set: $concatArrays (ghép mảng), $setDifference (loại bỏ phần tử trùng với mảng rỗng -> distinct), $filter (loại giá trị rỗng), $unwind + $group + $addToSet (tập hợp duy nhất).

1. Tạo dữ liệu: 2 tài liệu, mảng details và Info (cấu trúc khác nhau)

> db.demo420.insert({ "details": [{ "Value1": 10, "Value2": 20, "Value3": 30 }] });
> db.demo420.insert({ "Info": [{ "Value1": 10, "Value2": 20, "Value3": 300 }] });

2. Aggregation phức tạp (cách gốc)

> db.demo420.aggregate([
    {
        $project: {
            _id: 0,
            unique: {
                $filter: {
                    input: {
                        $setDifference: [
                            { $concatArrays: ["$Info.Value1", "$Info.Value2", "$Info.Value3"] },
                            []
                        ]
                    },
                    cond: { $ne: ["$$this", ""] }
                }
            }
        }
    },
    { $unwind: "$unique" },
    { $group: { _id: null, uniqueArray: { $addToSet: "$unique" } } }
]);

Vấn đề: Query gốc tham chiếu $Info.Value1 nhưng tài liệu 1 chỉ có details, không có Info -> kết quả có thể sai/null.

3. Cách chuẩn hơn: Chuẩn hóa tên trường -> gộp -> unique

> db.demo420.aggregate([
    // Chuẩn hóa: Đưa tất cả giá trị Value1, Value2, Value3 vào mảng "vals"
    { $project: { vals: { $concatArrays: ["$details.Value1", "$details.Value2", "$details.Value3", "$Info.Value1", "$Info.Value2", "$Info.Value3"] } } },
    { $unwind: "$vals" },
    { $group: { _id: null, uniqueArray: { $addToSet: "$vals" } } }
]);

4. Kết quả (giả sử dữ liệu có cả 2 trường)

{ "_id": null, "uniqueArray": [300, 20, 10] }

Giải thích toán tử:

  • $concatArrays: Ghép nhiều mảng thành 1.
  • $setDifference: [arr, []]: Trả về mảng distinct (loại trùng) - trick cũ.
  • $addToSet: Trong $group, tự động distinct (chuẩn hơn $setDifference trick).
  • $filter: Loại bỏ giá trị rỗng/null.

Best Practice: Thiết kế schema tránh tên trường khác nhau (details vs Info) cho cùng loại dữ liệu. Dùng schema nhất quán.