MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Mettre à jour le tableau là où il existe ou insérer un nouvel élément de tableau

Vous voulez .bulkWrite() pour ça. Il ne s'agit pas en fait d'une seule opération, vous souhaitez donc soumettre plusieurs opérations dans une seule demande. Essayez essentiellement d'écrire la mise à jour avec $set où les données existent ou $push les nouvelles données là où elles n'existent pas :

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

Le cas positif est simplement la valeur, et le $ne « annule » la correspondance d'égalité, ce qui signifie que l'élément n'existe pas. Bien sûr, le positionnel $ opérateur est utilisé avec $set où ça se passe

Étant donné les données, une seule des opérations correspondra réellement et s'appliquera en tant que mise à jour malgré l'envoi de deux opérations dans le "lot".

Si vous voulez également des "upserts" pour l'ensemble du document, vous devez ajouter une autre opération à la fin de celle-ci. Notez que vous ne pouvez pas appliquer "upsert" comme option sur l'une des autres déclarations, en particulier le $ne car cela créerait un nouveau document où l'élément de tableau n'existe pas, pas seulement le _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
  }}
])

Le $setOnInsert est l'aide principale ici à part cette dernière opération étant la seule marquée comme "upsert" . Cette combinaison garantit que là où le "document" principal est trouvé, rien ne se passe réellement, mais lorsqu'il n'est pas trouvé, le nouvel élément de tableau est ajouté.

En remarque, je suggérerais fortement de stocker les valeurs numériques sous forme numérique plutôt que sous forme de chaînes. Non seulement cela économise de l'espace dans la plupart des cas, mais c'est aussi beaucoup plus utile de cette façon.