Mongoose, perbarui nilai dalam larik objek


94

Apakah ada cara untuk memperbarui nilai dalam suatu objek?

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

Katakanlah saya ingin memperbarui nama dan nilai item untuk item di mana id = 2;

Saya telah mencoba yang berikut dengan luwak:

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

Masalah dengan pendekatan ini adalah bahwa ia memperbarui / mengatur seluruh objek, oleh karena itu dalam hal ini saya kehilangan bidang id.

Apakah ada cara yang lebih baik di luwak untuk mengatur nilai-nilai tertentu dalam sebuah array tetapi membiarkan nilai-nilai lain sendiri?

Saya juga bertanya hanya untuk Orang:

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().
});

Jawaban:


162

Anda dekat; Anda harus menggunakan notasi titik dalam penggunaan $operator pembaruan untuk melakukan itu:

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

Halo, ketika saya melakukan persis seperti yang Anda sarankan. board.update ({_id: board._id, "users.username": req.user.username}, {$ set: {"users. $. lastViewed": new Date ()}}, function (err) {} ); Saya mendapat kesalahan: tidak dapat menggunakan bagian (users of users.username) untuk melintasi elemen ({users: [{username: "nlm", _id: ObjectId ('583c8cc3813daa6c29f69cb0'), status: "invite", role: " pengulas "}]}). Apakah ada yang saya lakukan secara berbeda?
Peter Huang

4
Ini bekerja dengan baik, terima kasih. Namun, adakah cara untuk membuat item jika tidak ada dalam array?
Sergey Mell

@SergeyMell jika saya pikir itu mungkin solusi: stackoverflow.com/a/33577318/6470918
Grzegorz Brzęczyszczykiewicz

Bagaimana cara memperbarui nama untuk id = 2 di semua dokumen dalam koleksi?
Batang

1
Bagaimana ini akan bekerja jika Anda memiliki larik objek di dalam larik? Seperti, bukan hanya items.$.name, Anda punya items.users.$.status? apakah itu akan berhasil?
Stevie Star

18
model.update({"_id": 1, "items.id": "2"}, 
{$set: {"items.$.name": "yourValue","items.$.value": "yourvalue"}})

Dokumen Mongodb


12

Ada cara luwak untuk melakukannya.

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')
});

Metode ini berguna jika Anda melakukan operasi pada dokumen induk serta item array.
Jeremy

5

Untuk setiap dokumen, operator pembaruan $setbisa menyetel beberapa nilai , jadi daripada mengganti seluruh objek dalam itemslarik, Anda bisa menyetel bidang namedan valuedari objek satu per satu.

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

3

Ada satu hal yang perlu diingat, ketika Anda mencari objek dalam array berdasarkan lebih dari satu kondisi maka gunakan $ elemMatch

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

ini dokumentasinya



2

Di bawah ini adalah contoh cara memperbarui nilai dalam larik objek secara lebih dinamis.

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

Perhatikan bahwa dengan melakukannya dengan cara itu, Anda akan dapat memperbarui tingkat yang lebih dalam dari larik bersarang dengan menambahkan tambahan arrayFiltersseperti:

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

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

Saya harap ini membantu. Semoga berhasil!


0

Di luwak kita bisa update, seperti array sederhana

user.updateInfoByIndex(0,"test")

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

4
Jawaban Anda akan lebih membantu dengan beberapa penjelasan. Harap pertimbangkan untuk mengeditnya.
O. Jones

0

Dalam Mongoose, kita dapat mengupdate nilai array menggunakan notasi $setinside dot ( .) ke nilai tertentu dengan cara berikut

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

Maukah Anda mengedit jawaban dengan penjelasan, atau berhubungan dengan pertanyaan?
NIKHIL CM

1
Bisakah Anda melihat pertanyaan saya, luwak menghapus bagian dari kueri saya yang menggunakan $ [] meskipun berfungsi di CLI stackoverflow.com/questions/64223672/…
nrmad

0

Setelah mencoba solusi lain yang berfungsi dengan baik, tetapi kelemahan dari jawaban mereka adalah bahwa hanya bidang yang sudah ada yang akan memperbarui menambahkan upert padanya tidak akan melakukan apa-apa, jadi saya datang dengan ini.

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.