Bạn cần phải thay đổi cấu trúc tài liệu của bạn bằng cách cập nhật chúng. Bạn sẽ cần lặp qua từng tài liệu bằng cách sử dụng phương thức .forEach
sau đó $unset
tên của tất cả các trường bắt đầu bằng product_
. Từ đó bạn sẽ cần thêm các trường mới products
là mảng sản phẩm sử dụng toán tử cập nhật $set
. Điều đó đang được nói, bạn nên sử dụng "bulk" hoạt động để cập nhật tài liệu của bạn cho hiệu quả tối đa
var bulkOp = db.collection.initializeOrderedBulkOp();
var count = 0;
db.collection.find().forEach(function(doc) {
var allproducts = [];
for(var key in doc) {
if(Object.prototype.hasOwnProperty.call(doc, key) && /^product_\d+/.test(key)) {
var product = {};
product["name"] = key;
product["orderCancelled"] = doc[key]["orderCancelled"];
product["orderDelivered"] = doc[key]["orderDelivered"];
allproducts.push(product);
var unsetField = {};
unsetField[key] = "";
bulkOp.find({"_id": doc._id}).update({ "$unset": unsetField });
};
count++;
};
bulkOp.find({"_id": doc._id}).update({
"$set": { "products": allproducts }
});
count++;
if(count % 500 === 0) {
// Execute per 500 operations and re-init
bulkOp.execute();
bulkOp = db.collection.initializeOrderedBulkOp();
}
})
// clean up queues
if(count > 0) {
bulkOp.execute();
}
Tài liệu của bạn bây giờ sẽ trông như thế này:
{
"_id" : NumberLong(542),
"products" : [
{
"name" : "product_1",
"orderCancelled" : 0,
"orderDelivered" : 6
},
{
"name" : "product_2",
"orderCancelled" : 3,
"orderDelivered" : 16
},
{
"name" : "product_3",
"orderCancelled" : 5,
"orderDelivered" : 11
}
]
}
Rồi đến truy vấn tập hợp của bạn bằng cách sử dụng phương pháp .aggregate()
:
db.collection.aggregate([
{ "$match": { "_id": 542 } },
{ "$unwind": "$products" },
{ "$group": {
"_id": "$_id",
"maxOrderCancelled": { "$max": "$products.orderCancelled"},
"minOrderDelivvered": { "$min": "$products.orderDelivered"}
}}
])
Lợi nhuận nào:
{ "_id" : NumberLong(542), "maxOrderCancelled" : 5, "minOrderDelivvered" : 6 }
Từ version 3.2 bạn có thể sử dụng $max
và $min
trong giai đoạn $project
của bạn mà là một cách nhiều hơn nữa tốt hơn để làm điều này bởi vì có không cần phải $unwind
mảng của bạn đầu tiên.
db.collection.aggregate([
{ "$match": { "_id": 542 } },
{ "$project": {
"maxOrderCancelled": {
"$max": {
"$map": {
"input": "$products",
"as": "order",
"in": "$$orc.orderCancelled"
}
}
},
"minOrderDelivered": {
"$min": {
"$map": {
"input": "$products",
"as": "orc",
"in": "$$orc.orderDelivered"
}
}
}
}}
])
nào mang lại:
{ "_id" : NumberLong(542), "maxOrderCancelled" : 5, "minOrderDelivered" : 6 }
Tại sao bạn không đưa sản phẩm của bạn vào một mảng? –
@DmytroShevchenko tôi đã không nhận được bạn. Trên thực tế trong một trường hợp khác tôi cũng có thể cung cấp cho đếm cho 'orderDelivered' bởi' tên sản phẩm'. Điều gì sẽ là thiết kế trong trường hợp của bạn? – Shams
Hãy xem ví dụ về cấu trúc dữ liệu trong câu trả lời của tôi. Bạn có thể mô tả những gì bạn có nghĩa là bằng cách đếm cho 'orderDelivered' bởi' tên sản phẩm'? –