MongoDB aggiorna più record dell’array

Recentemente ho iniziato a utilizzare MongoDB e ho una domanda riguardante l’aggiornamento di array in un documento. Ho una struttura come questa:

{ "_id" : ObjectId(), "post" : "", "comments" : [ { "user" : "test", "avatar" : "/static/avatars/asd.jpg", "text" : "....." } { "user" : "test", "avatar" : "/static/avatars/asd.jpg", "text" : "....." } { "user" : "test", "avatar" : "/static/avatars/asd.jpg", "text" : "....." } ... ] } 

Sto cercando di eseguire la seguente query:

 update({"comments.user":"test"},{$set:{"comments.$.avatar": "new_avatar.jpg"}},false,true) 

Il problema è che aggiorna tutti i documenti, ma aggiorna solo il primo elemento dell’array in ogni documento. C’è un modo per aggiornare tutti gli elementi dell’array o dovrei provare a farlo manualmente? Grazie.

Non è ansible modificare più elementi dell’array in un’unica operazione di aggiornamento. Pertanto, dovrai ripetere l’aggiornamento per poter migrare i documenti che richiedono la modifica di più elementi di matrice. È ansible farlo iterando attraverso ogni documento della raccolta, applicando ripetutamente un aggiornamento con $elemMatch fino a quando il documento non ha tutti i relativi commenti sostituiti, ad esempio:

 db.collection.find (). forEach (function (doc) {
   fare {
     db.collection.update ({_ id: doc._id,
                           Commenti: {$ elemMatch: {user: "test",
                                                 avatar: {$ ne: "new_avatar.jpg"}}}},
                          {$ Set: { "commenti $ avatar..": "New_avatar.jpg"}});
   } while (db.getPrevError (). n! = 0);
 })

Si noti che se l’efficienza di questa operazione è un requisito per l’applicazione, è necessario normalizzare lo schema in modo tale che la posizione dell’avatar dell’utente sia memorizzata in un singolo documento, piuttosto che in ogni commento.

Una soluzione potrebbe essere la creazione di una funzione da utilizzare con un forEach e la sua valutazione (in modo che funzioni rapidamente). Supponendo che la tua raccolta sia “articolo”, potresti eseguire quanto segue:

 var runUpdate = function(){ db.article.find({"comments.user":"test").forEach( function(article) { for(var i in article.comments){ article.comments[i].avatar = 'new_avatar.jpg'; } db.article.save(article); }); }; db.eval(runUpdate); 

Se conosci gli indici che desideri aggiornare, puoi farlo senza problemi come questo:

 var update = { $set: {} }; for (var i = 0; i < indexesToUpdate.length; ++i) { update.$set[`comments.${indexesToUpdate[i]}. avatar`] = "new_avatar.jpg"; } Comments.update({ "comments.user":"test" }, update, function(error) { // ... }); 
  • essere consapevoli del fatto che l'IDE non deve accettare la syntax ma è ansible ignorarla.

Sembra che tu possa fare questo:

 db.yourCollection.update({"comments.user":"test"},{$set:{"comments.0.avatar": "new_avatar.jpg", "comments.1.avatar": "new_avatar.jpg", etc...}) 

Quindi se hai un piccolo numero noto di elementi dell’array, questo potrebbe essere un po ‘più facile da fare. Se vuoi qualcosa come “commenti. *. Avatar” – non sei sicuro di come farlo. Probabilmente non è così bello che tu abbia così tanta duplicazione dei dati che …