Můžete $pull
„první shoda“ z „vnějšího pole“ s odstraněním „všech vnitřních prvků“ jednoduše takto:
db.Events.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$.DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
To je v pořádku, pokud máte v "Distributions"
vždy pouze jeden záznam pole nebo alespoň jedna z těchto položek má podřízené položky pole, které by odpovídaly podmínce. Takto vypadá poziční $
operátor pracuje se všemi verzemi MongoDB.
Pokud by data měla "více" shod ve "vnějším" "Distributions"
pole, pak pokud máte MongoDB 3.6, můžete použít pozičně filtrovaný $[<identifier>]
operátor pro úpravu všech odpovídajících záznamů:
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
}
}}
]
}
)
V takovém případě arrayFilters
volba definuje podmínku, podle které porovnáváme položky ve "vnějším" poli, takže to může ve skutečnosti platit pro vše, co je srovnáno.
Nebo skutečně od $pull
v podstatě má tyto podmínky sám, pak můžete alternativně použít pouze poziční all $[]
operátor v tomto případě:
db.Event.updateMany(
{
"Distributions.DistributionData": {
"$elemMatch": {
"Key": null,
"Value": null,
"Children": null
}
}
},
{
"$pull": {
"Distributions.$[].DistributionData": {
"Key": null,
"Value": null,
"Children": null
}
}
}
)
V obou případech změní dokument v otázce odstraněním vnitřní položky se všemi null
klíče:
{
"_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")
]
}
]
}
Všechny podmínky "dotazu" používají $elemMatch
pro výběr dokumentu. To je ve skutečnosti vyžadováno pro poziční $
operátor za účelem získání "pozičního indexu" použitého pro "první shodu". I když to ve skutečnosti není "požadavek" ani pro pozičně filtrovaný $[<identifier>]
nebo poziční vše $[]
operátor, je stále užitečný, takže ani neuvažujete o aktualizaci dokumentů, které nebudou odpovídat podmínkám pozdější aktualizace ani $pull
nebo arrayFilters
možnosti.
Pokud jde o $pull
samotné, podmínky zde ve skutečnosti platí pro "každý" prvek pole, takže není potřeba $elemMatch
v této operaci, protože se již díváme na úroveň „prvku“.
Třetí příklad ukazuje, že poziční vše $[]
operátor může jednoduše použít tyto $pull
podmínky s ohledem na každý "vnitřní" prvek pole a bude platit pouze pro VŠECHNY "vnější" prvky pole. Tedy skutečný bod pozičně filtrovaného $[<identifier>]
výraz je "pouze" zpracovat ty "vnější" prvky pole, které skutečně odpovídají "vnitřnímu" stavu. Proto používáme $elemMatch
v úvahu pro shodu každého "vnitřního" prvku pole.
Pokud ve skutečnosti nemáte alespoň MongoDB 3.6, pak používáte první formulář a pravděpodobně to budete opakovat, dokud aktualizace konečně nevrátí žádné další upravené dokumenty, což naznačuje, že nezůstaly žádné další prvky odpovídající podmínce.
Existuje mnohem podrobnější popis „alternativ“ jako přístupů v How to Update Multiple Array Elements v mongodb, ale pokud vaše data buď vyhovují původnímu případu, nebo skutečně máte k dispozici MongoDB 3.6, pak je to správné. přístup zde.
Pokud chcete vidět plný efekt nové syntaxe pro MongoDB 3.6. toto je změna dokumentu v otázce, kterou jsem použil k ověření prohlášení o aktualizaci zde:
{
"_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")
]
}
]
}
Což v podstatě duplikuje některé položky „vnější“ i „vnitřní“, aby se ukázalo, jak příkaz odstraní všechny null
hodnoty.
POZNÁMKA
arrayFilters
jsou specifikovány v argumentu "options" pro.update()
a podobně jako u metod je syntaxe obecně kompatibilní se všemi nejnovějšími verzemi ovladačů a dokonce i s těmi před vydáním MongoDB 3.6.To však neplatí pro
mongo
shell, protože způsob, jakým je tam metoda implementována ( "ironicky pro zpětnou kompatibilitu"),arrayFilters
argument není rozpoznán a odstraněn interní metodou, která analyzuje možnosti, aby byla zajištěna "zpětná kompatibilita" s předchozími verzemi serveru MongoDB a "starší".update()
Syntaxe volání API.Pokud tedy chcete použít příkaz v
mongo
shell nebo jiné "shell based" produkty (zejména Robo 3T) potřebujete nejnovější verzi buď z vývojové větve nebo z produkčního vydání od 3.6 nebo vyšší.Zejména Robo 3T je zde stále spojen s tím, že je založen na prostředí MongoDB 3.4. Takže i když se připojujete ke schopné instanci MongoDB 3.6, tyto možnosti nebudou z tohoto programu předány serveru. Doporučuje se zůstat pouze u shellu a podporovaných produktů, i když existují některé další nabídky, které nemají stejná omezení.