105 votes

MongoDB : Comment mettre à jour un seul sous-élément dans un tableau, référencé par l'index dans le tableau ?

J'essaie de mettre à jour un seul sous-élément contenu dans un tableau dans un document mongodb. Je veux référencer le champ en utilisant son index de tableau (les éléments du tableau n'ont pas de champs dont je peux garantir qu'ils seront des identifiants uniques). Il semble que cela devrait être facile à faire, mais je n'arrive pas à trouver la syntaxe.

Voici ce que je veux faire en pseudo-json.

Avant :

{
  _id : ...,
  other_stuff ... ,
  my_array : [
    { ... old content A ... },
    { ... old content B ... },
    { ... old content C ... }
  ]
}

Après :

{
  _id : ...,
  other_stuff ... ,
  my_array : [
    { ... old content A ... },
    { ... NEW content B ... },
    { ... old content C ... }
  ]
}

Il semble que la requête devrait être quelque chose comme ça :

//pseudocode
db.my_collection.update(
  {_id: ObjectId(document_id), my_array.1 : 1 },
  {my_array.$.content: NEW content B }
)

Mais ça ne marche pas. J'ai passé beaucoup trop de temps à chercher dans la documentation de mongodb et à essayer différentes variations de cette syntaxe (par exemple en utilisant $slice etc.). Je ne trouve pas d'explication claire sur la manière d'effectuer ce type de mise à jour dans MongoDB.

9voto

Une façon élégante de le faire en Javascript, avec des backticks, est :

 const index = 1;

 ...  {   $set: { [`myArray.${index}.value`]: "new content"}  },  ...

7voto

Lorsqu'il est nécessaire de mettre à jour un élément d'un tableau sans savoir qu'il s'agit d'un index réel mais en ayant un identifiant unique de l'élément.

db.getCollection('profiles').update(
  {
    'userId':'4360a380-1540-45d9-b902-200f2d346263',
    'skills.name':'css'
  },
  {
      $set: {'skills.$.proficiencyLevel': 5}
  }, 
  {
      multi: true
  }
)

3voto

Samuel Cabral Points 41

Vous pouvez utiliser la fonction updateOne de mongoDB en passant l'index de l'élément dans le tableau, si la clé de l'option ancien contenu B est "valeur" par exemple :

[
...
"value" : "old content A"
"value" : "old content B"
"value" : "old content C"
...
]

la commande devrait être comme ceci :

db.collection.updateOne({"_id" : "...,"},{$set: {"my_array.1.value": "NEW content B"}})

3voto

Si vous voulez mettre à jour le nom de l'auteur du témoignage ayant _id = 60c4918d74c30165ba585c14 du document suivant :

"business": {
    "ownerId": "60a5ebad7432d91b853c0277",
    "testimonials": [
        {
            "_id": "60c4912877dd5664f2201b08",
            "authorName": "user1",
            "authorBio": "User from 10 years",
            "image": "user1/img1",
            "review": "asdfiuahsdfpoiuashdpfoaspdlfkjn;alsfpuoh"
        },
        {
            "_id": "60c4918d74c30165ba585c14",
            "authorName": "user2",
            "authorBio": "User from 3 years",
            "image": "user/img1",
            "review": "asdpfuahsfljnsadfoihsf."
        }
    ],
    "createdAt": "2021-06-11T20:12:56.666Z",
    "updatedAt": "2021-06-12T11:11:56.696Z",

}

Alors la requête suivante de la mangouste fonctionne :

await BusinessModel.updateOne(
        {
            '_id': Mongoose.Types.ObjectId(businessId),
            'testimonials._id': Mongoose.Types.ObjectId('60c4918d74c30165ba585c14')
        },
        {
            $set: { 'testimonials.$.authorName' : 'new author name' } 
        }
    );

Voir également https://docs.mongodb.com/drivers/node/fundamentals/crud/write-operations/embedded-arrays/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X