Bạn có thể $pull
"đối sánh đầu tiên" từ "mảng bên ngoài" với việc xóa "tất cả các phần tử bên trong" chỉ bằng cách thực hiện:
db.Events.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$.DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
Điều đó tốt nếu bạn chỉ có một mục nhập trong "Distributions"
mảng hoặc ít nhất chỉ một trong số các mục nhập đó có các mục nhập mảng con sẽ phù hợp với điều kiện. Đây là cách $
vị trí toán tử hoạt động với tất cả các phiên bản của MongoDB.
Nếu dữ liệu có "nhiều" đối sánh trong "Distributions"
"bên ngoài" thì nếu bạn có MongoDB 3.6, bạn có thể áp dụng $[<identifier>]
được lọc theo vị trí toán tử để sửa đổi tất cả các mục nhập phù hợp:
db.Events.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$[element].DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"arrayFilters": [
{ "element.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}}
]
}
)
Trong trường hợp đó, arrayFilters
tùy chọn xác định một điều kiện mà chúng tôi so khớp các mục nhập trong mảng "ngoài" để điều này trên thực tế có thể áp dụng cho mọi thứ được khớp.
Hoặc thực sự là vì $pull
về cơ bản có các điều kiện đó, sau đó bạn có thể luân phiên sử dụng tất cả $[]
theo vị trí trong trường hợp này:
db.Event.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$[].DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
Cả hai trường hợp đều thay đổi tài liệu trong câu hỏi bằng cách xóa mục bên trong có tất cả null
các phím:
{
"_id" : UUID("cf397865-c000-4f51-8959-1aae84769706"),
"CreationDateTime" : ISODate("2016-05-06T05:09:14.589Z"),
"WKT" : "",
"Distributions" : [
{
"_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType" : 1,
"DistributionData" : [
{
"Key" : "Topic",
"Value" : "Topics",
"Children" : null
},
{
"Key" : "Message",
"Value" : "test",
"Children" : null
}
],
"Schedules" : [
ISODate("2016-05-06T05:09:56.988Z")
]
}
]
}
Tất cả các điều kiện "truy vấn" đều sử dụng $elemMatch
để lựa chọn tài liệu. Điều này thực sự cần thiết cho $
vị trí để có được "chỉ số vị trí" được sử dụng cho "trận đấu đầu tiên". Trong khi đây thực sự không phải là "yêu cầu" đối với $[<identifier>]
được lọc theo vị trí hoặc vị trí tất cả $[]
, nó vẫn hữu ích, vì vậy bạn thậm chí không cần xem xét các tài liệu để cập nhật sẽ không phù hợp với các điều kiện cập nhật sau của $pull
hoặc arrayFilters
tùy chọn.
Đối với $pull
chính nó, các điều kiện ở đây thực sự áp dụng cho "mỗi" phần tử mảng, vì vậy không cần $elemMatch
trong hoạt động đó vì chúng tôi đã xem xét cấp "phần tử".
Ví dụ thứ ba cho thấy rằng tất cả $[]
có vị trí nhà điều hành có thể chỉ cần sử dụng $pull
đó điều kiện xem xét của từng phần tử mảng "bên trong" và sẽ chỉ áp dụng cho TẤT CẢ các phần tử mảng "bên ngoài". Vì vậy, điểm thực tế của $[<identifier>]
được lọc theo vị trí biểu thức là "chỉ" xử lý các phần tử mảng "bên ngoài" thực sự phù hợp với điều kiện "bên trong". Do đó, tại sao chúng tôi sử dụng $elemMatch
đang cân nhắc để khớp từng phần tử mảng "bên trong".
Nếu bạn thực sự không có MongoDB 3.6 ít nhất thì bạn đang sử dụng biểu mẫu đầu tiên và có khả năng lặp lại điều đó cho đến khi các bản cập nhật cuối cùng trả lại không có tài liệu sửa đổi nào nữa cho thấy rằng không còn phần tử nào phù hợp với điều kiện.
Có một bài viết chi tiết hơn về "các lựa chọn thay thế" như các phương pháp tiếp cận tại Cách cập nhật nhiều phần tử mảng trong mongodb, nhưng miễn là dữ liệu của bạn phù hợp với trường hợp ban đầu hoặc bạn thực sự có sẵn MongoDB 3.6, thì đây là chính xác tiếp cận ở đây.
Nếu bạn muốn xem toàn bộ tác dụng của cú pháp mới cho MongoDB 3.6. đây là sự thay đổi đối với tài liệu trong câu hỏi mà tôi đã sử dụng để xác minh các tuyên bố cập nhật tại đây:
{
"_id" : UUID("cf397865-c000-4f51-8959-1aae84769706"),
"CreationDateTime" : ISODate("2016-05-06T05:09:14.589Z"),
"WKT" : "",
"Distributions" : [
{
"_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType" : 1,
"DistributionData" : [
{
"Key" : "Topic",
"Value" : "Topics",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
},
{
"Key" : "Message",
"Value" : "test",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
}
],
"Schedules" : [
ISODate("2016-05-06T05:09:56.988Z")
]
},
{
"_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
"DeliveryType" : 1,
"DistributionData" : [
{
"Key" : "Topic",
"Value" : "Topics",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
},
{
"Key" : "Message",
"Value" : "test",
"Children" : null
},
{
"Key" : null,
"Value" : null,
"Children" : null
}
],
"Schedules" : [
ISODate("2016-05-06T05:09:56.988Z")
]
}
]
}
Về cơ bản nó sẽ sao chép một số mục nhập cả "bên ngoài" và "bên trong" để hiển thị cách câu lệnh loại bỏ tất cả null
giá trị.
LƯU Ý
arrayFilters
được chỉ định trong đối số "tùy chọn" cho.update()
và giống như các phương pháp, cú pháp nói chung tương thích với tất cả các phiên bản trình điều khiển phát hành gần đây và thậm chí cả những phiên bản trước khi phát hành MongoDB 3.6.Tuy nhiên, điều này không đúng với
mongo
shell, vì cách phương thức được triển khai ở đó ("trớ trêu thay cho khả năng tương thích ngược")arrayFilters
đối số không được công nhận và bị xóa bởi một phương thức nội bộ phân tích cú pháp các tùy chọn để cung cấp "khả năng tương thích ngược" với các phiên bản máy chủ MongoDB trước đó và "kế thừa".update()
Cú pháp gọi API.Vì vậy, nếu bạn muốn sử dụng lệnh trong
mongo
shell hoặc các sản phẩm "dựa trên shell" khác (đặc biệt là Robo 3T), bạn cần có phiên bản mới nhất từ nhánh phát triển hoặc phiên bản sản xuất từ 3.6 trở lên.Đáng chú ý ở đây là Robo 3T vẫn được gắn với việc dựa trên trình bao MongoDB 3.4. Vì vậy, ngay cả khi kết nối với phiên bản MongoDB 3.6 có khả năng, các tùy chọn này sẽ không được chuyển đến máy chủ từ chương trình này. Bạn chỉ nên sử dụng shell và các sản phẩm được hỗ trợ, mặc dù có một số dịch vụ khác không có cùng giới hạn.