MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Aktualisieren Sie das Array, wo es vorhanden ist, oder fügen Sie ein neues Array-Element ein

Sie möchten .bulkWrite() dafür. Dies ist eigentlich kein einzelner Vorgang, daher möchten Sie mehrere Vorgänge in einer einzigen Anforderung übermitteln. Versuchen Sie im Wesentlichen, das Update mit $set zu schreiben wo Daten existieren oder $push die neuen Daten, wo sie nicht existieren:

db.collection.bulkWrite([
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": "10" },
    "update": { 
      "$set": { "option.$.price": "30" }
    }
  }},
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": { "$ne": "10" } },
    "update": {
      "$push": { "option": { "weight": "10", "price": "30" } }
    }
  }}
])

Der positive Fall ist einfach der Wert und der $ne "negiert" die Gleichheitsübereinstimmung, was bedeutet, dass das Element nicht existiert. Natürlich der positionsbezogene $ Betreiber wird mit $set verwendet wo es tut

Angesichts der Daten wird nur eine der Operationen tatsächlich übereinstimmen und als Aktualisierung gelten, obwohl zwei Operationen im "Batch" gesendet werden.

Wenn Sie auch "Upserts" für das gesamte Dokument wünschen, müssen Sie am Ende eine weitere Operation hinzufügen. Beachten Sie, dass Sie "upsert" nicht als Option auf eine der anderen Anweisungen anwenden können, insbesondere auf $ne denn das würde ein neues Dokument erstellen, in dem das Array-Element nicht existiert, nicht nur die _id :

db.collection.bulkWrite([
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": "10" },
    "update": { 
      "$set": { "option.$.price": "30" }
    }
  }},
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": { "$ne": "10" } },
    "update": {
      "$push": { "option": { "weight": "10", "price": "30" } }
    }
  }},
  { "updateOne": {
    "filter": { "_id": 1 },
    "update": {
      "$setOnInsert": {
        "option": [
           { "weight": "10", "price": "30" }
         ]
      }
    },
    "upsert": true
  }}
])

Der $setOnInsert ist hier die Haupthilfe, abgesehen davon, dass die letzte Operation die einzige ist, die als "upsert" gekennzeichnet ist . Diese Kombination stellt sicher, dass dort, wo das primäre "Dokument" gefunden wird, eigentlich nichts passiert, aber wenn es nicht gefunden wird, wird das neue Array-Element hinzugefügt.

Als Randnotiz würde ich dringend empfehlen, numerische Werte tatsächlich als numerische und nicht als Zeichenfolgen zu speichern. Das spart in den meisten Fällen nicht nur Platz, sondern ist auf diese Weise auch viel nützlicher.