Możesz $pull
„pierwsze dopasowanie” z „tablicy zewnętrznej” z usunięciem „wszystkich elementów wewnętrznych” po prostu wykonując:
db.Events.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$.DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
To dobrze, jeśli masz tylko jeden wpis w "Distributions"
tablica lub przynajmniej jeden z tych wpisów ma wpisy podrzędne, które pasują do warunku. W ten sposób pozycyjny $
operator działa ze wszystkimi wersjami MongoDB.
Jeśli dane miałyby „wiele” dopasowań w „zewnętrznym” "Distributions"
tablicę, to jeśli masz MongoDB 3.6, możesz zastosować filtrowany pozycyjnie $[<identifier>]
operator do modyfikacji wszystkich pasujących wpisów:
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
}
}}
]
}
)
W takim przypadku arrayFilters
opcja definiuje warunek, według którego dopasowujemy wpisy w tablicy "zewnętrznej" tak, że może to faktycznie dotyczyć wszystkiego, co jest dopasowane.
Albo rzeczywiście od $pull
zasadniczo ma te warunki same w sobie, możesz alternatywnie po prostu użyć pozycyjnego all $[]
operator w tym przypadku:
db.Event.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$[].DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
Każdy przypadek zmienia dokument w pytaniu, usuwając element wewnętrzny ze wszystkimi null
klawisze:
{
"_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")
]
}
]
}
Wszystkie warunki „zapytanie” używają $elemMatch
do wyboru dokumentów. Jest to faktycznie wymagane dla pozycyjnego $
operatora w celu uzyskania „indeksu pozycji” używanego do „pierwszego dopasowania”. Chociaż nie jest to w rzeczywistości „wymaganie” dla filtrowanego pozycyjnie $[<identifier>]
lub pozycyjne wszystkie $[]
operatora, jest to nadal przydatne, więc nawet nie bierzesz pod uwagę dokumentów do aktualizacji, które nie będą pasować do późniejszych warunków aktualizacji ani $pull
lub arrayFilters
opcje.
Co do $pull
same, warunki tutaj faktycznie odnoszą się do "każdego" elementu tablicy, więc nie ma potrzeby stosowania $elemMatch
w tej operacji, ponieważ już patrzymy na poziom "elementu".
Trzeci przykład pokazuje, że pozycyjne wszystkie $[]
operator może po prostu użyć tych $pull
warunki z uwzględnieniem każdego „wewnętrznego” elementu tablicy i będą miały zastosowanie tylko do WSZYSTKICH „zewnętrznych” elementów tablicy. Tak więc rzeczywisty punkt filtrowanego pozycyjnie $[<identifier>]
wyrażenie polega na przetwarzaniu „tylko” tych „zewnętrznych” elementów tablicy, które faktycznie pasują do warunku „wewnętrzny”. Dlatego używamy $elemMatch
w rozważaniu dopasowania każdego „wewnętrznego” elementu tablicy.
Jeśli tak naprawdę nie masz MongoDB 3.6, to używasz pierwszego formularza i prawdopodobnie powtarzasz to, dopóki aktualizacje w końcu nie zwrócą już zmodyfikowanych dokumentów, wskazując, że nie ma już elementów spełniających warunek.
Jest o wiele bardziej szczegółowy opis „alternatyw” w temacie Jak zaktualizować wiele elementów tablicy w mongodb, ale dopóki twoje dane albo pasują do początkowego przypadku, albo faktycznie masz dostęp do MongoDB 3.6, to jest to poprawne podejdź tutaj.
Jeśli chcesz zobaczyć pełny efekt nowej składni MongoDB 3.6. to jest zmiana w dokumencie w pytaniu, którego użyłem do weryfikacji oświadczeń o aktualizacji tutaj:
{
"_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")
]
}
]
}
Który zasadniczo powiela niektóre wpisy zarówno „zewnętrzne”, jak i „wewnętrzne”, aby pokazać, w jaki sposób instrukcja usuwa wszystkie null
wartości.
UWAGA arrayFilters
są określone w argumencie "opcje" dla .update()
i podobnie jak metody, składnia jest ogólnie zgodna ze wszystkimi najnowszymi wersjami sterowników wydań, a nawet tymi przed wydaniem MongoDB 3.6.
Nie dotyczy to jednak mongo
powłoki, ponieważ sposób, w jaki metoda jest tam zaimplementowana ( "jak na ironię dla wstecznej kompatybilności"), arrayFilters
argument nie jest rozpoznawany i usuwany przez wewnętrzną metodę, która analizuje opcje w celu zapewnienia „zgodności wstecznej” z wcześniejszymi wersjami serwera MongoDB i „starszego” .update()
Składnia wywołań API.
Więc jeśli chcesz użyć polecenia w mongo
shell lub inne produkty "oparte na powłoce" (zwłaszcza Robo 3T), potrzebujesz najnowszej wersji z gałęzi rozwojowej lub wydania produkcyjnego w wersji 3.6 lub nowszej.
Szczególnie tutaj Robo 3T jest nadal związany z tym, że jest oparty na powłoce MongoDB 3.4. Tak więc nawet podczas łączenia się z wydajną instancją MongoDB 3.6 opcje te nie zostaną przekazane do serwera z tego programu. Zaleca się pozostanie tylko przy powłoce i wspieranych produktach, chociaż istnieją inne oferty, które nie mają tych samych ograniczeń.