Bạn đã là một phần của con đường đến đó bằng cách xác định chính xác các thao tác bạn cần thực hiện. Nhưng tất nhiên $ sort
không phải là công cụ sửa đổi hợp lệ cho $ addToSet
vì câu thần chú MongoDB là "các bộ không được coi là sắp xếp theo thứ tự" :
Vấn đề khác ở đây được chỉ ra bởi lỗi là bạn không thể sử dụng nhiều toán tử cập nhật (chẳng hạn như $ addToSet
và $ push
) trên cùng một đường dẫn đến một thuộc tính tại cùng một thời điểm. Trên thực tế, "không có thứ tự" nào đối với việc thực thi các toán tử cập nhật khác nhau, vì vậy chúng không đảm bảo rằng $ addToSet
xảy ra trước $ push
. Trên thực tế, chúng có thể hoạt động song song, đó là lý do tại sao lỗi và điều này không được phép.
Câu trả lời tất nhiên là "hai" câu lệnh cập nhật. Một cho $ addToSet
và một để áp dụng $ sort
bằng cách "đẩy" một mảng trống qua $ each
,
Nhưng vì chúng tôi thực sự không muốn "đợi" mỗi bản cập nhật hoàn thành, đây là những gì API hoạt động "Hàng loạt" dành cho. Vì vậy, bạn có thể gửi cả hai hướng dẫn đến máy chủ trong một gửi và nhận một phản hồi:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({ "name": "Risas" }).update({
"$addToSet": {
"propiedades": { "name": "cola", "cantidad": 1 }
}
});
bulk.find({ "name": "Risas" }).update({
"$push": {
"propiedades": {
"$each": [ ], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
Vì vậy, đây thực sự vẫn chỉ là một yêu cầu đến máy chủ và một phản hồi. Nó vẫn là hoạt động "hai" nhưng chi phí và khả năng một số luồng lấy trạng thái tạm thời của upadte là không thể bỏ qua.
Có một giải pháp thay thế cho cách tiếp cận này là di chuyển logic "thiết lập phát hiện" vào .find ()
phần của câu lệnh cập nhật và sau đó chỉ cần áp dụng $ push
trong đó (các) thành viên sẽ được thêm vào "tập hợp" chưa tồn tại:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({
"name": "Risas",
"propiedades": {
"$not": { "$elemMatch": { "name": "cola", "cantidad": 1 } }
}
}).update({
"$push": {
"propiedades": {
"$each": [{ "name": "cola", "cantidad": 1 }], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
Tất nhiên, điều phức tạp ở đó là nếu bạn đang thêm "nhiều" phần tử mảng ở đây, bạn sẽ cần phải bao bọc $ not
và $ elemMacth
kiểm tra trong $ và
điều kiện và sau đó nếu "chỉ một" trong số các phần tử đó hợp lệ thì không thể thêm một mình nó.
Bạn có thể "thử" loại thao tác đó với "nhiều" mục "trước", nhưng sau đó bạn nên có một thực thi "dự phòng" của từng phần tử mảng riêng lẻ với cùng một logic như trên để "kiểm tra" khả năng "đẩy" cho từng phần tử.
Vì vậy, $ addToSet
làm cho phần thứ hai đó trở nên dễ dàng với nhiều mục nhập mảng. Đối với một mục nhập, khá đơn giản chỉ cần "truy vấn" và $ push
, đối với nhiều hơn một, có lẽ đường dẫn ngắn hơn để sử dụng mẫu "đầu tiên" với $ addToSet
và $ push
một mảng trống để "sắp xếp" kết quả vì việc áp dụng mẫu thứ hai có nghĩa là vẫn phải kiểm tra nhiều bản cập nhật.