sql >> Databasteknik >  >> NoSQL >> MongoDB

pushOrModify som operatör för mongo underdokument

Detta kräver faktiskt "två" (eller "tre" med upsert ) uppdateringssatser och är en av de mycket goda anledningarna till att "bulk"-operationer finns.

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 om du faktiskt ville inkludera en "upsert" för grunddokumentet för "SweetTown" då måste du separera det problemet i ett eget 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 allmänna konceptet där är att endast tillämpa $setOnInsert åtgärd när en "upsert" faktiskt inträffar. För att säkerställa att detta bara händer i det här fallet är de andra operationerna som faktiskt tittar på arrayelementet inte markerade med "upsert" alternativ. Den delen är avsiktligt.

Hur du än ser på det är det bara möjligt för en av dessa operationer för att faktiskt göra någon ändring i databasen, eftersom antingen elementet hittas eller inte, eller till och med dokumentet inte hittas och ett nytt skapas.

I inget fall är det möjligt att göra den typen av operation i en enda uppdateringssats. Men eftersom "Mass"-operationer egentligen bara är en begäran med en svar, när det gäller din applikation så behövde den bara prata med servern en gång att få servern att prova alla dessa tre saker och returnera ett svar.

För tidigare användning av Direct Bulk API är den alternativa syntaxen:

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. Introduktion av uppslagsdiagram i MongoDB

  2. Hur man hanterar stora databaser effektivt

  3. ScaleGrid Hosting för Redis™ på ditt eget AWS-konto

  4. Skalbar fillagring