sql >> Database teknologi >  >> NoSQL >> MongoDB

Fjern objekt fra indlejret array efter flere kriterier

Du kan $pull det "første match" fra det "ydre array" med at fjerne "alle de indre elementer" blot ved at gøre:

db.Events.updateMany(
  {
    "Distributions.DistributionData": {
      "$elemMatch": {
        "Key": null,
        "Value": null,
        "Children": null
      }
    }
  },
  {
    "$pull": {
      "Distributions.$.DistributionData": { 
        "Key": null,
        "Value": null,
        "Children": null
      }
    }
  }
)

Det er fint, hvis du kun har én post i "Distributions" array eller i det mindste kun én af disse poster har underordnede array-indgange, som ville matche betingelsen. Dette er, hvordan den positionelle $ operatør fungerer med alle versioner af MongoDB.

Hvis dataene ville have "flere" match i den "ydre" "Distributions" array, så hvis du har MongoDB 3.6, kan du anvende den positionsfiltrerede $[<identifier>] operatør for at ændre alle matchede poster:

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
        }
      }}
    ]
  }
)

I så fald arrayFilters option definerer en betingelse, hvorved vi matcher indgange i det "ydre" array, så dette faktisk kan gælde for alt, der matches.

Eller faktisk siden $pull i det væsentlige har disse betingelser i sig selv, så kan du alternativt bare bruge den positionelle alle $[] operatør i dette tilfælde:

db.Event.updateMany(
  {
    "Distributions.DistributionData": {
      "$elemMatch": {
        "Key": null,
        "Value": null,
        "Children": null
      }
    }
  },
  {
    "$pull": {
      "Distributions.$[].DistributionData": { 
        "Key": null,
        "Value": null,
        "Children": null
      }
    }
  }
)

Begge tilfælde ændrer dokumentet i spørgsmålet ved at fjerne det indre element med alle null nøgler:

{
        "_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")
                        ]
                }
        ]
}

"Query"-betingelserne bruger alle $elemMatch til dokumentvalg. Dette er faktisk påkrævet for den positionelle $ operatør for at opnå "positionsindekset", der blev brugt til det "første match". Selvom dette faktisk ikke er et "krav" for hverken den positionsfiltrerede $[<identifier>] eller den positionelle alle $[] operatør, er det stadig nyttigt, så du ikke engang overvejer dokumenter til opdatering, som ikke vil matche de senere opdateringsbetingelser for hverken $pull eller arrayFilters muligheder.

Hvad angår $pull selv, gælder betingelserne her faktisk for "hvert" array-element, så der er ikke behov for $elemMatch i den operation, da vi allerede ser på "element"-niveauet.

Det tredje eksempel viser, at den positionelle alle $[] operatør kan blot bruge disse $pull betingelser i betragtning af hvert "indre" array-element og vil kun gælde for ALLE "ydre" array-elementer. Så det faktiske punkt for den positionsfiltrerede $[<identifier>] udtryk er at "kun" behandle de "ydre" array-elementer, som faktisk matcher den "indre" tilstand. Derfor bruger vi $elemMatch i overvejelserne om at matche hvert "indre" array-element.

Hvis du i det mindste ikke har MongoDB 3.6, bruger du den første formular og gentager sandsynligvis det, indtil opdateringerne endelig ikke returnerer flere ændrede dokumenter, der indikerer, at der ikke er flere elementer tilbage, der matcher betingelsen.

Der er en meget mere detaljeret beskrivelse af "alternativerne" som tilgange til Sådan opdaterer du flere array-elementer i mongodb, men så længe dine data enten passer til det oprindelige tilfælde, eller du faktisk har MongoDB 3.6 tilgængelig, så er dette det rigtige nærme sig her.

Hvis du vil se den fulde effekt af den nye syntaks til MongoDB 3.6. dette er ændringen af ​​dokumentet i spørgsmålet, jeg brugte til at bekræfte opdateringsudsagn her:

{
    "_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")
                    ]
            }
    ]
}

Som dybest set dublerer nogle poster både "ydre" og "indre" for at vise, hvordan sætningen fjerner alle null værdier.

BEMÆRK arrayFilters er angivet i "options"-argumentet for .update() og ligesom metoder er syntaksen generelt kompatibel med alle nyere udgivelsesdriverversioner og endda dem før udgivelsen af ​​MongoDB 3.6.

Dette er dog ikke sandt for mongo shell, da måden metoden er implementeret der ("ironisk nok for bagudkompatibilitet") arrayFilters argument genkendes og fjernes ikke af en intern metode, der analyserer mulighederne for at levere "bagudkompatibilitet" med tidligere MongoDB-serverversioner og en "legacy" .update() API-opkaldssyntaks.

Så hvis du vil bruge kommandoen i mongo shell eller andre "skalbaserede" produkter (især Robo 3T), skal du bruge en seneste version fra enten udviklingsgrenen eller produktionsudgivelsen fra 3.6 eller nyere.

Robo 3T, især her, er stadig bundet til at være baseret på en MongoDB 3.4-skal. Så selv når der oprettes forbindelse til en egnet MongoDB 3.6-instans, vil disse muligheder ikke blive videregivet til serveren fra dette program. Det tilrådes kun at blive med shell og understøttede produkter, selvom der er nogle andre tilbud, som ikke har samme begrænsning.




  1. Sletning af en nøgle/værdi fra eksisterende MongoDB-indgang

  2. Sådan installeres Redis

  3. Kan denne teknologi stable skala?

  4. Mongodb Forøg værdi inde i indlejret array