MongoDB **không hỗ trợ wildcard** (như details.*.Age) trực tiếp trong projection của find(). Để loại trừ trường lồng nhau động (không biết tên key cha), bạn dùng **Aggregation Pipeline** với $objectToArray -> lọc -> $arrayToObject.
1. Tạo dữ liệu: Object details có key động Info1, Info2 (mỗi key chứa object Name, Age)
> db.demo413.insertOne({
"_id": "101",
"details": {
"Info1": { "Name": "Chris", "Age": 21 },
"Info2": { "Name": "David", "Age": 23 }
}
});
2. Xem dữ liệu
> db.demo413.find();
Kết quả: details.Info1, Info2 đều có Name, Age.
3. Aggregation: Loại bỏ trường Age khỏi TẤT CẢ sub-object trong details
> db.demo413.aggregate([
// B1: Chuyển object details -> mảng [{k: "Info1", v: {Name, Age}}, {k: "Info2", v: {Name, Age}}]
{ $project: { "details": { $objectToArray: "$details" } } },
// B2: Loại bỏ trường "Age" trong mỗi phần tử v (value) của mảng
{ $project: { "details.v.Age": 0 } },
// B3: Chuyển mảng k/v ngược lại thành object
{ $project: { "details": { $arrayToObject: "$details" } } }
]);
4. Kết quả
{ "_id": "101", "details": { "Info1": { "Name": "Chris" }, "Info2": { "Name": "David" } } }
Giải thích quy trình:
$objectToArray: Biến object lồng thành mảng cặp key-value (k, v).- Projection
{ "details.v.Age": 0 }: Loại bỏ Age trong value (v) của mỗi phần tử mảng details. $arrayToObject: Ghép mảng k/v ngược thành object.
Cách khác (MongoDB 4.2+): Dùng $set / $unset trong update với $[] (all positional) nếu muốn **cập nhật vĩnh viễn** vào DB:
db.demo413.updateMany({}, { $unset: { "details.$[].Age": "" } });
Cách này đơn giản hơn nhiều cho việc sửa dữ liệu thực tế.