Mungo, aktualisiere Werte in einem Array von Objekten


86

Gibt es eine Möglichkeit, Werte in einem Objekt zu aktualisieren?

{
  _id: 1,
  name: 'John Smith',
  items: [{
     id: 1,
     name: 'item 1',
     value: 'one'
  },{
     id: 2,
     name: 'item 2',
     value: 'two'
  }]
}

Nehmen wir an, ich möchte die Namen- und Wertelemente für das Element mit id = 2 aktualisieren.

Ich habe folgendes mit Mungo versucht:

var update = {name: 'updated item2', value: 'two updated'};
Person.update({'items.id': 2}, {'$set':  {'items.$': update}}, function(err) { ...

Das Problem bei diesem Ansatz ist, dass das gesamte Objekt aktualisiert / festgelegt wird. In diesem Fall verliere ich daher das ID-Feld.

Gibt es eine bessere Möglichkeit für Mungos, bestimmte Werte in einem Array festzulegen, andere Werte jedoch in Ruhe zu lassen?

Ich habe auch nur nach der Person gefragt:

Person.find({...}, function(err, person) {
  person.items ..... // I might be able to search through all the items here and find item with id 2 then update the values I want and call person.save().
});

Antworten:


149

Du bist nah dran; Sie sollten die Punktnotation verwenden, wenn Sie den $Aktualisierungsoperator verwenden, um dies zu tun:

Person.update({'items.id': 2}, {'$set': {
    'items.$.name': 'updated item2',
    'items.$.value': 'two updated'
}}, function(err) { ...

Hallo, wenn ich genau das mache, hast du vorgeschlagen. board.update ({_id: board._id, "users.username": req.user.username}, {$ set: {"users. $. lastViewed": neues Datum ()}}, Funktion (err) {} ); Ich habe eine Fehlermeldung erhalten: Ich kann den Teil (Benutzer von users.username) nicht zum Durchlaufen des Elements verwenden ({users: [{username: "nlm", _id: ObjectId ('583c8cc3813daa6c29f69cb0'), Status: "eingeladen", Rolle: " Rezensent "}]}). Gibt es etwas, das ich anders gemacht habe?
Peter Huang

4
Das funktioniert super, danke. Gibt es jedoch eine Möglichkeit, ein Element zu erstellen, wenn es nicht im Array enthalten ist?
Sergey Mell

@ SergeyMell, wenn ich denke, dass das eine Lösung sein könnte: stackoverflow.com/a/33577318/6470918
Grzegorz Brzęczyszczykiewicz

Wie aktualisiere ich den Namen für id = 2 in allen Dokumenten einer Sammlung?
Rod

1
Wie würde dies funktionieren, wenn Sie ein Array von Objekten in einem Array hätten? Wie statt nur items.$.name, hattest du items.users.$.status? Funktioniert das?
Stevie Star


8

Es gibt einen Mungo-Weg, dies zu tun.

const itemId = 2;
const query = {
  item._id: itemId 
};
Person.findOne(query).then(doc => {
  item = doc.items.id(itemId );
  item["name"] = "new name";
  item["value"] = "new value";
  doc.save();

  //sent respnse to client
}).catch(err => {
  console.log('Oh! Dark')
});

4

Für jedes Dokument, das Update Bediener $setkann mehrere Werte gesetzt , so anstatt das gesamte Objekt in der Ersatz - itemsArray können Sie die festlegen nameund valueFelder des Objekts einzeln.

{'$set':  {'items.$.name': update.name , 'items.$.value': update.value}}

3

Beachten Sie Folgendes , wenn Sie das Objekt im Array anhand mehrerer Bedingungen durchsuchen und dann $ elemMatch verwenden

Person.update(
   {
     _id: 5,
     grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } }
   },
   { $set: { "grades.$.std" : 6 } }
)

Hier ist die Dokumentation



0

Im Mungo können wir wie ein einfaches Array aktualisieren

user.updateInfoByIndex(0,"test")

User.methods.updateInfoByIndex = function(index, info) ={
    this.arrayField[index]=info
    this.save()
}

4
Ihre Antwort wäre mit einigen Erklärungen hilfreicher. Bitte überlegen Sie, es zu bearbeiten.
O. Jones

0

In Mongoose können wir den Array-Wert mithilfe der $setInside-Dot- .Notation ( ) auf folgende Weise auf einen bestimmten Wert aktualisieren

db.collection.update({"_id": args._id, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})

Würden Sie bitte die Antwort mit Erklärungen bearbeiten oder sich auf die Frage beziehen?
NIKHIL CM

0

Nachdem ich andere Lösungen ausprobiert hatte, die gut funktionierten, aber die Gefahr ihrer Antworten besteht darin, dass nur bereits vorhandene Felder aktualisiert werden und das Hinzufügen von Upsert nichts bewirken würde. Deshalb habe ich mir das ausgedacht.

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })

0

Im Folgenden finden Sie ein Beispiel für eine dynamischere Aktualisierung des Werts im Array von Objekten.

Person.findOneAndUpdate({_id: id}, 
{ 
  "$set": {[`items.$[outer].${propertyName}`]: value} 
},
{ 
  "arrayFilters": [{ "outer.id": itemId }]
},
function(err, response) {
  ...
})

Beachten Sie, dass Sie auf diese Weise noch tiefere Ebenen des verschachtelten Arrays aktualisieren können, indem Sie Folgendes hinzufügen arrayFilters:

"$set": {[`items.$[outer].innerItems.$[inner].${propertyName}`]: value} 

"arrayFilters":[{ "outer.id": itemId },{ "inner.id": innerItemId }]

Ich hoffe, es hilft. Viel Glück!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.