sql >> Database >  >> NoSQL >> MongoDB

pushOrModify like operator voor mongo subdocument

Dit vereist eigenlijk "twee" (of "drie" met upsert ) update-instructies en is een van de zeer goede redenen waarom "Bulk" -bewerkingen bestaan.

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

Of als u eigenlijk een "upsert" . wilt opnemen voor het basisdocument van "SweetTown" dan moet je die zorg opsplitsen in zijn eigen 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
  }}
])

Dus het algemene concept is om alleen pas de $setOnInsert toe actie wanneer een "upsert" daadwerkelijk voorkomt. Om ervoor te zorgen dat dit alleen in dit geval gebeurt, worden de andere bewerkingen die daadwerkelijk naar het array-element kijken niet gemarkeerd met de "upsert" keuze. Dat deel is met opzet.

Hoe je het ook bekijkt, het is altijd maar mogelijk voor één van die bewerkingen om daadwerkelijk enige wijziging in de database aan te brengen, aangezien het element wordt gevonden of niet, of zelfs het document niet wordt gevonden en een nieuwe wordt gemaakt.

In geen geval is het mogelijk om een ​​dergelijke bewerking in een enkele update-instructie uit te voeren. Maar aangezien "Bulk"-bewerkingen eigenlijk maar één zijn verzoek met één antwoord, dan hoeft u wat uw toepassing betreft maar één keer met de server te praten om de server al deze drie dingen te laten proberen en een antwoord terug te sturen.

Voor eerder gebruik van de directe Bulk API is de alternatieve syntaxis:

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. Datumnotatie mangoest

  2. MongoDB gebruikt COLLSCAN bij het retourneren van alleen _id

  3. Hoe Redis te gebruiken met Python

  4. Hoe te RegisterClassMap voor alle klassen in een naamruimte voor MongoDb?