MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Usuń obiekt z zagnieżdżonej tablicy według wielu kryteriów

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ń.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. nazwa pola ClassName jest wstawiana do mongodb przez morphia

  2. MongoDb wyłącza się z kodem 100

  3. Jak zoptymalizować wydajność ClusterControl i jego komponentów?

  4. MongoDB $cond

  5. Jak wysłać zapytanie do kolekcji dokumentów podrzędnych za pomocą MongoDB i sterownika C#?