Quá trình ở đây thực sự khá đơn giản, nó chỉ khác nhau ở nơi bạn muốn "tìm hoặc tạo" các phần tử trong mảng.
Đầu tiên, giả sử các phần tử cho mỗi khóa đã có sẵn, thì trường hợp đơn giản là truy vấn phần tử và cập nhật với chỉ mục được trả về thông qua positional $
nhà điều hành:
db.collection.update(
{
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
}
{ "$set": { "attrs.$.value": "20" }
)
Điều đó sẽ chỉ sửa đổi phần tử phù hợp mà không ảnh hưởng đến phần tử khác.
Trong trường hợp thứ hai khi "tìm hoặc tạo" được yêu cầu và khóa cụ thể có thể không tồn tại, thì bạn sử dụng "hai" câu lệnh cập nhật. Nhưng API hoạt động hàng loạt cho phép bạn thực hiện điều này trong một yêu cầu duy nhất tới máy chủ với một phản hồi duy nhất:
var bulk = db.collection.initializeOrderedBulkOp();
// Try to update where exists
bulk.find({
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
"$set": { "attrs.$.value": "30" }
});
// Try to add where does noes not exist
bulk.find({
"_id": docId,
"attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
"$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});
bulk.execute();
Logic cơ bản là lần đầu tiên cập nhật được thực hiện để khớp một phần tử với các giá trị được yêu cầu giống như đã thực hiện trước đó. Điều kiện khác kiểm tra xem phần tử hoàn toàn không được tìm thấy ở đâu bằng cách đảo ngược logic đối sánh với $not
.
Trong trường hợp không tìm thấy phần tử mảng thì phần tử mới có giá trị để thêm qua $push
.
Tôi thực sự nên nói thêm rằng vì chúng tôi đang đặc biệt tìm kiếm các kết quả phủ định ở đây, nên luôn luôn là một ý kiến hay để khớp với "tài liệu" mà bạn định cập nhật bằng một số nhận dạng duy nhất như _id
Chìa khóa. Mặc dù có thể thực hiện được với các bản cập nhật "nhiều", nhưng bạn cần phải cẩn thận về những gì bạn đang làm.
Vì vậy, trong trường hợp đang chạy quy trình "tìm hoặc tạo" thì phần tử không được so khớp sẽ được thêm vào mảng một cách chính xác, mà không can thiệp vào các phần tử khác, bản cập nhật trước đó cho kết quả phù hợp dự kiến cũng được áp dụng theo cách tương tự:
{
"_id" : ObjectId("55b570f339db998cde23369d"),
"attrs" : [
{
"key" : "A1",
"type" : "T1",
"value" : "20"
},
{
"key" : "A2",
"type" : "T2",
"value" : "14"
},
{
"key" : "A1",
"type" : "T2",
"value" : "30"
}
]
}
Đây là một mô hình đơn giản để làm theo và tất nhiên Các hoạt động hàng loạt ở đây loại bỏ mọi chi phí liên quan bằng cách gửi và nhận nhiều yêu cầu đến và từ máy chủ. Tất cả điều này hoạt động một cách nhanh chóng mà không can thiệp vào các yếu tố khác có thể tồn tại hoặc không.
Bên cạnh đó, có những lợi ích bổ sung của việc giữ dữ liệu trong một mảng để dễ dàng truy vấn và phân tích như được hỗ trợ bởi các toán tử tiêu chuẩn mà không cần phải hoàn nguyên về xử lý máy chủ JavaScript để duyệt qua các phần tử.