Mongoose, nesneler dizisindeki değerleri güncelle


94

Bir nesnedeki değerleri güncellemenin bir yolu var mı?

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

İd = 2 olan öğe için isim ve değer öğelerini güncellemek istiyorum diyelim.

Aşağıdakileri w / firavun faresi denedim:

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

Bu yaklaşımla ilgili sorun, tüm nesneyi güncellemesi / ayarlamasıdır, bu nedenle bu durumda kimlik alanını kaybediyorum.

Firavun faresinde bir dizide belirli değerleri ayarlamanın ancak diğer değerleri olduğu gibi bırakmanın daha iyi bir yolu var mı?

Ayrıca sadece Kişi için de sorguladım:

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

Yanıtlar:


162

Yakınsın; Bunu yapmak için $güncelleme operatörünü kullanırken noktalı gösterimi kullanmalısınız :

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

Merhaba, yaptığım zaman tam olarak sen önerdin. board.update ({_id: board._id, "users.username": req.user.username}, {$ set: {"users. $. lastViewed": yeni Tarih ()}}, fonksiyon (err) {} ); Bir hata aldım: parçayı (users.username kullanıcıları) öğeye geçmek için kullanamıyorum ({kullanıcılar: [{kullanıcı adı: "nlm", _id: ObjectId ('583c8cc3813daa6c29f69cb0'), durum: "davet edildi", rol: " gözden geçiren "}]}). Farklı yaptığım bir şey var mı?
Peter Huang

4
Bu harika çalışıyor, teşekkürler. Bununla birlikte, dizide değilse bir öğe oluşturmanın herhangi bir yolu var mı?
Sergey Mell

@SergeyMell bunun bir çözüm olabileceğini düşünüyorsam: stackoverflow.com/a/33577318/6470918
Grzegorz Brzęczyszczykiewicz

Bir koleksiyondaki tüm belgelerde id = 2 adını nasıl güncellerim?
Rod

1
Bir dizi içinde nesneler dizisi olsaydı bu nasıl çalışır? Sadece yerine sahip items.$.nameoldun items.users.$.statusmu? Işe yarar mı?
Stevie Star

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

Mongodb belgesi


12

Bunu yapmanın firavun faresi bir yolu var.

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

Bu yöntem, ana belgede olduğu kadar dizi öğesinde de bir işlem yapıyorsanız kullanışlıdır.
Jeremy

5

Her belge için, güncelleme operatörü $setolabilir birden çok değer ayarlamak , bu yüzden ziyade bütün nesneyi değiştirerek daha itemsdizide, ayarlayabilirsiniz nameve valuebireysel nesnenin alanları.

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

3

Unutulmaması gereken bir şey var, dizideki nesneyi birden fazla koşula göre aradığınızda $ elemMatch kullanın

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

işte dokümanlar



2

Aşağıda, nesneler dizisindeki değerin daha dinamik bir şekilde nasıl güncelleneceğine dair bir örnek verilmiştir.

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

Bunu bu şekilde yaparak, aşağıdakiler arrayFiltersgibi ek ekleyerek iç içe dizinin daha derin seviyelerini güncelleyebileceğinizi unutmayın :

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

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

Umut ediyorum bu yardım eder. İyi şanslar!


0

Firavun faresinde basit bir dizi gibi güncelleme yapabiliriz

user.updateInfoByIndex(0,"test")

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

4
Cevabınız bazı açıklamalarla daha faydalı olacaktır. Lütfen düzenlemeyi düşünün.
O. Jones

0

Mongoose'da, $setiç nokta ( .) gösterimini kullanarak dizi değerini aşağıdaki şekilde belirli bir değere güncelleyebiliriz

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

Cevabı açıklamalarla birlikte düzenler misiniz, yoksa soruyla ilişkilendirir misiniz?
NIKHIL CM

1
Soruma bir bakabilir misiniz, firavun faresi, CLI stackoverflow.com/questions/64223672/…
nrmad

0

İyi çalışan diğer çözümleri denedikten sonra, ancak cevaplarının tuzağı, yalnızca mevcut alanların güncellenmesi ve buna ek olarak hiçbir şey yapmamasıdır, bu yüzden bunu buldum.

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.