sql >> Databáze >  >> NoSQL >> MongoDB

pushOrModify jako operátor pro vnořený dokument mongo

To ve skutečnosti vyžaduje "dva" (nebo "tři" s upsert ) aktualizační prohlášení a je to jeden z velmi dobrých důvodů, proč existují "hromadné" operace.

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

Nebo pokud jste skutečně chtěli zahrnout "upsert" pro základní dokument "SweetTown" pak musíte tuto obavu rozdělit do vlastního testu:

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

Obecný koncept je tedy pouze použijte $setOnInsert akce při "upsert" skutečně dochází. Aby se zajistilo, že k tomu dojde pouze v tomto případě, ostatní operace, které se skutečně dívají na prvek pole, nejsou označeny "upsert" volba. Ta část je záměrná.

Ať se na to podíváte z jakéhokoli úhlu, vždy je to možné jen jednou těchto operací skutečně provést jakoukoli úpravu v databázi, protože buď je prvek nalezen, nebo ne, nebo dokonce není nalezen dokument a je vytvořen nový.

V žádném případě není možné provést tento druh operace v jediném příkazu aktualizace. Protože však „hromadné“ operace jsou ve skutečnosti pouze jedna požádat o jednu odpověď, pak pokud jde o vaši aplikaci, pak stačilo jen mluvit se serverem jednou aby server vyzkoušel všechny tyto tři věci a vrátil odpověď.

Pro dřívější použití přímého Bulk API je alternativní syntaxe:

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. Mongoose dvouúrovňové populace pomocí KeystoneJs

  2. Mongodb Sharding - žádný takový příkaz:'addShard'

  3. Mongoose:jak nastavit pole schématu jako ID?

  4. Jak spočítám všechny dokumenty v kolekci a použiji kont v řadiči s MongoDB a Express.js?