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

pushOrModify som operatør for mongo underdokument

Dette kræver faktisk "to" (eller "tre" med upsert ) opdateringserklæringer og er en af ​​de meget gode grunde til, at "bulk"-operationer eksisterer.

db.collection.bulkWrite([
  // Attempt to update the matched element
  { "updateOne": {
    "filter": { 
      "name": "SweetTown",
      "residents.name": "Bob"
    },
    "update": {
      "$set": { "residents.$.reputation": 30 }    
    }
  },
  // $push the element where not matched
  { "updateOne": {
    "filter": {
      "name": "SweetTown",
      "residents.name": { "$ne": "Bob" } 
    },
    "update": { 
      "$push": { 
        "residents": { "name": "Bob", "reputation": 30 } 
      }
    } 
  }}
])

Eller hvis du faktisk ønskede at inkludere en "upsert" til grunddokumentet "SweetTown" så skal du udskille den bekymring i sin egen test:

db.collection.bulkWrite([
  // Attempt to update the matched element
  { "updateOne": {
    "filter": { 
      "name": "SweetTown",
      "residents.name": "Bob"
    },
    "update": {
      "$set": { "residents.$.reputation": 30 }    
    }
  },
  // $push the element where not matched
  { "updateOne": {
    "filter": {
      "name": "SweetTown",
      "residents.name": { "$ne": "Bob" } 
    },
    "update": { 
      "$push": { 
        "residents": { "name": "Bob", "reputation": 30 } 
      }
    } 
  }},
  // Only use $setOnInsert when actually an upsert
  { "updateOne": {
      "filter": {
        "name": "SweetTown"
      },
      "update": {
        "$setOnInsert": {
           "residents": [{ "name": "Bob", "reputation": 30 }]
        }
      },
      "upsert": true
  }}
])

Så det generelle koncept er kun anvend $setOnInsert handling, når en "upsert" faktisk forekommer. For at sikre, at dette kun sker i dette tilfælde, er de andre operationer, der rent faktisk ser på array-elementet, ikke markeret med "upsert" mulighed. Den del er med vilje.

Uanset hvordan du ser på det, er det kun muligt for én af disse operationer til rent faktisk at foretage ændringer i databasen, da enten elementet er fundet eller ej, eller endda dokumentet ikke findes, og et nyt oprettes.

Det er i intet tilfælde muligt at udføre den slags operationer i en enkelt opdateringserklæring. Men da "bulk"-operationer i virkeligheden kun er én anmodning med én svar, så hvad angår din ansøgning, behøvede den kun at tale med serveren én gang at få serveren til at prøve alle disse tre ting og returnere et svar.

For tidligere brug af den direkte Bulk API er den alternative syntaks:

var bulk = db.collection.initializeOrderedBulkOp();

// $set matched where existing
bulk.find({ "name": "SweetTown", "residents.name": "Bob" }).updateOne({
  "$set": { "residents.$.reputation": 30 }
});

// $push where not existing
bulk.find({ "name": "SweetTown", "residents.name": { "$ne": "Bob" } }).updateOne({
  "$push": { "residents": { "name": "Bob", "reputation": 30 } }
});

// Attempt to upsert only
bulk.find({ "name": "SweetTown" }).upsert().updateOne({
  "$setOnInsert": {
    "residents": [{ "name": "Bob", "reputation": 30 }]
  }
})

bulk.execute();



  1. Spring Data MongoDB Repository med brugerdefineret samlingsnavn

  2. mongoDB kort/reducere minus reducere

  3. Hvordan bruger man MongoDB-aggregering til paginering?

  4. MongoDB:Upserting og Sub-dokumenter