Để gộp nhiều mảng thành một và lọc phần tử, dùng $setUnion, $ifNull, $filter trong stage $project của aggregate.
Dữ liệu mẫu
> db.demo119.insertOne({
"_id": 101,
"WebDetails": [
{ "ImagePath": "/all/image1", "isCorrect": "false" },
{ "ImagePath": "/all/image2", "isCorrect": "true" }
],
"ClientDetails": [
{ "Name": "Chris", "isCorrect": "false" },
{ "Name": "David", "isCorrect": "true" }
]
});
{ "acknowledged" : true, "insertedId" : 101 }
Pipeline aggregate
> db.demo119.aggregate([
{ "$project": {
"AllDetails": {
"$filter": {
"input": {
"$setUnion": [
{ "$ifNull": [ "$WebDetails", [] ] },
{ "$ifNull": [ "$ClientDetails", [] ] }
]
},
"as": "out",
"cond": { "$eq": [ "$$out.isCorrect", "false" ] }
}
}
}},
{ "$match": { "AllDetails.0": { "$exists": true } } }
]);
Kết quả
{ "_id" : 101, "AllDetails" : [ { "ImagePath" : "/all/image1", "isCorrect" : "false" }, { "Name" : "Chris", "isCorrect" : "false" } ] }
Giải thích:
$ifNull: Xử lý trường hợp mảng null/không tồn tại → trả về mảng rỗng$setUnion: Gộp 2 mảng, loại bỏ phần tử trùng lặp (so sánh toàn bộ object)$filter: Lọc phần tử có isCorrect="false"$match: Chỉ giữ document có AllDetails không rỗng
Lưu ý: $setUnion so sánh toàn bộ object. Nếu cấu trúc khác nhau (ImagePath vs Name), không bị coi là trùng. Dùng $concatArrays nếu muốn giữ trùng lặp và thứ tự.