Hướng dẫn how do you update all arrays of objects in mongodb? - làm cách nào để cập nhật tất cả các mảng đối tượng trong mongodb?

Điều này trên thực tế liên quan đến vấn đề lâu dài tại http://jira.mongodb.org/browse/server-1243 nơi thực tế có một số thách thức đối với cú pháp rõ ràng hỗ trợ "tất cả các trường hợp" trong đó mảng mutiple phù hợp tìm. Trên thực tế, có những phương pháp đã có sẵn rằng "viện trợ" trong các giải pháp cho vấn đề này, chẳng hạn như các hoạt động hàng loạt đã được thực hiện sau bài đăng gốc này.

Vẫn không thể cập nhật nhiều hơn một phần tử mảng phù hợp trong một câu lệnh cập nhật duy nhất, vì vậy ngay cả với bản cập nhật "đa", tất cả những gì bạn sẽ có thể cập nhật chỉ là một phần tử được toán học trong mảng cho mỗi tài liệu trong đó bản tường trình.

Giải pháp tốt nhất có thể hiện tại là tìm và lặp lại tất cả các tài liệu phù hợp và xử lý các bản cập nhật hàng loạt, ít nhất sẽ cho phép nhiều hoạt động được gửi trong một yêu cầu duy nhất với phản hồi số ít. Bạn có thể tùy chọn sử dụng .aggregate() để giảm nội dung mảng được trả về trong kết quả tìm kiếm chỉ với các điều kiện phù hợp với các điều kiện cho lựa chọn cập nhật:

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$project": {
        "events": {
            "$setDifference": [
               { "$map": {
                   "input": "$events",
                   "as": "event",
                   "in": {
                       "$cond": [
                           { "$eq": [ "$$event.handled", 1 ] },
                           "$$el",
                           false
                       ]
                   }
               }},
               [false]
            ]
        }
    }}
]).forEach(function(doc) {
    doc.events.forEach(function(event) {
        bulk.find({ "_id": doc._id, "events.handled": 1  }).updateOne({
            "$set": { "events.$.handled": 0 }
        });
        count++;

        if ( count % 1000 == 0 ) {
            bulk.execute();
            bulk = db.collection.initializeOrderedBulkOp();
        }
    });
});

if ( count % 1000 != 0 )
    bulk.execute();

Phần .aggregate() sẽ hoạt động khi có một mã định danh "duy nhất" cho mảng hoặc tất cả nội dung cho mỗi phần tử tạo thành chính phần tử "duy nhất". Điều này là do toán tử "Đặt" trong $setDifference được sử dụng để lọc bất kỳ giá trị

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
0 nào được trả về từ hoạt động
db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
1 được sử dụng để xử lý mảng cho các trận đấu.

Nếu nội dung mảng của bạn không có các phần tử duy nhất, bạn có thể thử một cách tiếp cận thay thế với

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
2:

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])

Trong trường hợp giới hạn là nếu "xử lý" trên thực tế, một trường có nghĩa là có mặt ở các cấp tài liệu khác thì bạn có thể sẽ nhận được kết quả không được xem xét, nhưng vẫn ổn khi trường đó chỉ xuất hiện ở một vị trí tài liệu và là một trận đấu bình đẳng.

Các bản phát hành trong tương lai (bài 3.1 MongoDB) khi viết sẽ có hoạt động

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
3 đơn giản hơn:

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$project": {
        "events": {
            "$filter": {
                "input": "$events",
                "as": "event",
                "cond": { "$eq": [ "$$event.handled", 1 ] }
            }
        }
    }}
])

Và tất cả các bản phát hành hỗ trợ .aggregate() có thể sử dụng phương pháp sau với

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
5, nhưng việc sử dụng toán tử đó làm cho nó trở thành cách tiếp cận hiệu quả nhất do mở rộng mảng trong đường ống:

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$unwind": "$events" },
    { "$match": { "events.handled": 1 } },
    { "$group": {
        "_id": "$_id",
        "events": { "$push": "$events" }
    }}        
])

Trong tất cả các trường hợp phiên bản MongoDB hỗ trợ "con trỏ" từ đầu ra tổng hợp, thì đây chỉ là vấn đề chọn cách tiếp cận và lặp lại kết quả với cùng một khối mã được hiển thị để xử lý các câu lệnh cập nhật hàng loạt. Hoạt động hàng loạt và "con trỏ" từ đầu ra tổng hợp được giới thiệu trong cùng một phiên bản (MongoDB 2.6) và do đó thường làm việc trong tay để xử lý.

Trong các phiên bản trước đó, có lẽ tốt nhất là chỉ sử dụng

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
6 để trả về con trỏ và lọc ra việc thực thi các câu lệnh để chỉ số lần phần tử mảng được khớp với các lần lặp
db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])
7:

db.collection.find({ "events.handled": 1 }).forEach(function(doc){ 
    doc.events.filter(function(event){ return event.handled == 1 }).forEach(function(event){
        db.collection.update({ "_id": doc._id },{ "$set": { "events.$.handled": 0 }});
    });
});

Nếu bạn hoàn toàn quyết tâm thực hiện các bản cập nhật "đa" hoặc cho rằng cuối cùng hiệu quả hơn so với xử lý nhiều bản cập nhật cho mỗi tài liệu phù hợp, thì bạn luôn có thể xác định số lượng mảng tối đa có thể xảy ra và chỉ thực hiện bản cập nhật "đa" mà nhiều thời gian, cho đến khi về cơ bản không có thêm tài liệu để cập nhật.

Một cách tiếp cận hợp lệ cho các phiên bản MongoDB 2.4 và 2.2 cũng có thể sử dụng .aggregate() để tìm giá trị này:

var result = db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$unwind": "$events" },
    { "$match": { "events.handled": 1 } },
    { "$group": {
        "_id": "$_id",
        "count": { "$sum": 1 }
    }},
    { "$group": {
        "_id": null,
        "count": { "$max": "$count" }
    }}
]);

var max = result.result[0].count;

while ( max-- ) {
    db.collection.update({ "events.handled": 1},{ "$set": { "events.$.handled": 0 }},{ "multi": true })
}

Dù thế nào đi chăng nữa, có một số điều bạn không muốn làm trong bản cập nhật:not want to do within the update:

  1. Không "một lần bắn" cập nhật mảng: Nếu bạn nghĩ rằng có thể hiệu quả hơn khi cập nhật toàn bộ nội dung mảng trong mã và sau đó chỉ

    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$redact": {
            "$cond": {
                "if": {
                    "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
                },
                "then": "$$DESCEND",
                "else": "$$PRUNE"
            }
        }}
    ])
    
    9 toàn bộ mảng trong mỗi tài liệu. Điều này có vẻ nhanh hơn để xử lý, nhưng không có gì đảm bảo rằng nội dung mảng không thay đổi kể từ khi nó được đọc và bản cập nhật được thực hiện. Mặc dù
    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$redact": {
            "$cond": {
                "if": {
                    "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
                },
                "then": "$$DESCEND",
                "else": "$$PRUNE"
            }
        }}
    ])
    
    9 vẫn là toán tử nguyên tử, nhưng nó sẽ chỉ cập nhật mảng với những gì nó "nghĩ" là dữ liệu chính xác và do đó có khả năng ghi đè lên mọi thay đổi xảy ra giữa đọc và viết.
    Where if you think it might be more efficient to update the whole array content in code and then just
    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$redact": {
            "$cond": {
                "if": {
                    "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
                },
                "then": "$$DESCEND",
                "else": "$$PRUNE"
            }
        }}
    ])
    
    9 the whole array in each document. This might seem faster to process, but there is no guarantee that the array content has not changed since it was read and the update is performed. Though
    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$redact": {
            "$cond": {
                "if": {
                    "$eq": [ { "$ifNull": [ "$handled", 1 ] }, 1 ]
                },
                "then": "$$DESCEND",
                "else": "$$PRUNE"
            }
        }}
    ])
    
    9 is still an atomic operator, it will only update the array with what it "thinks" is the correct data, and thus is likely to overwrite any changes occurring between read and write.

  2. Không tính toán các giá trị chỉ mục để cập nhật: trong đó tương tự như cách tiếp cận "One Shot" mà bạn chỉ cần thực hiện vị trí đó

    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$project": {
            "events": {
                "$filter": {
                    "input": "$events",
                    "as": "event",
                    "cond": { "$eq": [ "$$event.handled", 1 ] }
                }
            }
        }}
    ])
    
    1 và vị trí
    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$project": {
            "events": {
                "$filter": {
                    "input": "$events",
                    "as": "event",
                    "cond": { "$eq": [ "$$event.handled", 1 ] }
                }
            }
        }}
    ])
    
    2 (v.v.)
    Where similar to the "one shot" approach you just work out that position
    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$project": {
            "events": {
                "$filter": {
                    "input": "$events",
                    "as": "event",
                    "cond": { "$eq": [ "$$event.handled", 1 ] }
                }
            }
        }}
    ])
    
    1 and position
    db.collection.aggregate([
        { "$match": { "events.handled": 1 } },
        { "$project": {
            "events": {
                "$filter": {
                    "input": "$events",
                    "as": "event",
                    "cond": { "$eq": [ "$$event.handled", 1 ] }
                }
            }
        }}
    ])
    
    2 ( and so on ) are the elements to update and code these in with and eventual statement like:

    { "$set": {
        "events.0.handled": 0,
        "events.2.handled": 0
    }}
    

    Một lần nữa, vấn đề ở đây là "giả định" mà các giá trị chỉ mục đó được tìm thấy khi tài liệu được đọc là cùng một giá trị chỉ mục trong mảng TH tại thời điểm cập nhật. Nếu các mục mới được thêm vào mảng theo cách thay đổi thứ tự thì các vị trí đó không còn hiệu lực và thực tế các mục sai được cập nhật.

Vì vậy, cho đến khi có một cú pháp hợp lý được xác định để cho phép nhiều phần tử mảng phù hợp được xử lý trong câu lệnh cập nhật đơn thì cách tiếp cận cơ bản là cập nhật từng phần tử mảng phù hợp trong một câu lệnh bừa bãi (lý tưởng là với số lượng lớn) hoặc thực sự tạo ra các phần tử mảng tối đa Để cập nhật hoặc tiếp tục cập nhật cho đến khi không có thêm kết quả sửa đổi được trả về. Ở bất kỳ giá nào, bạn nên "luôn luôn" xử lý các vị trí

db.collection.aggregate([
    { "$match": { "events.handled": 1 } },
    { "$project": {
        "events": {
            "$filter": {
                "input": "$events",
                "as": "event",
                "cond": { "$eq": [ "$$event.handled", 1 ] }
            }
        }
    }}
])
3 cập nhật trên phần tử mảng phù hợp, ngay cả khi đó chỉ cập nhật một phần tử cho mỗi câu lệnh.

Trên thực tế, các hoạt động hàng loạt là giải pháp "tổng quát" để xử lý bất kỳ hoạt động nào hoạt động để trở thành "nhiều hoạt động" và vì có nhiều ứng dụng này hơn là chỉ cập nhật các yếu tố mảng mutiple có cùng giá trị, nên tất nhiên nó đã được triển khai Đã, và nó hiện là cách tiếp cận tốt nhất để giải quyết vấn đề này.

Làm cách nào để cập nhật toàn bộ một mảng trong MongoDB?

Để thực hiện bản cập nhật trên tất cả các phần tử mảng được nhúng của từng tài liệu phù hợp với truy vấn của bạn, hãy sử dụng toán tử vị trí được lọc $ []. Toán tử vị trí được lọc $ [] chỉ định các phần tử mảng phù hợp trong tài liệu cập nhật.use the filtered positional operator $[] . The filtered positional operator $[] specifies the matching array elements in the update document.

Làm cách nào để cập nhật nhiều yếu tố trong MongoDB?

Cập nhật nhiều trường của một tài liệu.Chúng tôi có thể sử dụng các nhà khai thác $ Set và $ Inc để cập nhật bất kỳ trường nào trong MongoDB.Toán tử $ SET sẽ đặt giá trị mới được chỉ định trong khi toán tử $ Inc sẽ tăng giá trị theo giá trị được chỉ định.use $set and $inc operators to update any field in MongoDB. The $set operator will set the newly specified value while the $inc operator will increase the value by a specified value.

Làm thế nào để bạn cập nhật một đối tượng trong MongoDB?

Shell MongoDB cung cấp các phương pháp sau để cập nhật các tài liệu trong một bộ sưu tập:..
Để cập nhật một tài liệu duy nhất, hãy sử dụng DB.thu thập.Cập nhật ().
Để cập nhật nhiều tài liệu, hãy sử dụng DB.thu thập.Updatemany ().
Để thay thế một tài liệu, sử dụng DB.thu thập.thay thế ().

Làm cách nào để cập nhật một mảng lồng nhau trong MongoDB?

Cập nhật các mảng lồng nhau kết hợp với toán tử vị trí $ [] $ [], kết hợp với toán tử $ [] tất cả các toán tử vị trí, có thể được sử dụng để cập nhật các mảng lồng nhau.Các bản cập nhật sau đây các giá trị lớn hơn hoặc bằng 8 trong các lớp lồng nhau.câu hỏi mảng nếu các lớp liên quan.The $[] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades. questions array if the associated grades.