Đối với MongoDB 3.6 và mới hơn, hãy sử dụng khung tổng hợp với $replaceRoot
đường ống có thể được áp dụng cùng với $mergeObjects
toán tử dưới dạng newRoot
biểu thức.
Biểu thức này
{ "$mergeObjects": ["$subdoc", "$$ROOT"] }
sẽ hợp nhất các trường cấp cao nhất trong tài liệu với các trường trong các trường nhúng phụ để cuối cùng, hoạt động tổng hợp của bạn sẽ như sau:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [ "$subdoc", "$$ROOT" ]
}
} },
{ "$project": { "subdoc": 0 } }
])
Nếu không, bạn sẽ cần một cơ chế để lấy tất cả các khóa động mà bạn cần để lắp ráp $project
động tài liệu. Điều này có thể thực hiện được thông qua Map-Reduce
. Thao tác mapreduce sau đây sẽ điền vào một tập hợp riêng biệt với tất cả các khóa dưới dạng _id
giá trị:
mr = db.runCommand({
"mapreduce": "my_collection",
"map" : function() {
for (var key in this.subdoc) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
Để nhận danh sách tất cả các khóa động, hãy chạy riêng biệt trên tập hợp kết quả:
db[mr.result].distinct("_id")
["field2", "field3", ...]
Bây giờ được cung cấp danh sách ở trên, bạn có thể tập hợp $project
của mình tài liệu đường ống tổng hợp bằng cách tạo một đối tượng sẽ có các thuộc tính của nó được đặt trong một vòng lặp. Thông thường $project
của bạn tài liệu sẽ có cấu trúc sau:
var project = {
"$project": {
"field1": 1,
"field2": "$subdoc.field2",
"field3": "$subdoc.field3"
}
};
Vì vậy, bằng cách sử dụng danh sách các khóa tài liệu phụ ở trên, bạn có thể tạo động ở trên bằng cách sử dụng reduce()
phương pháp:
var subdocKeys = db[mr.result].distinct("_id"),
obj = subdocKeys.reduce(function (o, v){
o[v] = "$subdoc." + v;
return o;
}, { "field1": 1 }),
project = { "$project": obj };
db.collection.aggregate([project]);