マングース、オブジェクトの配列の値を更新します


94

オブジェクトの値を更新する方法はありますか?

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

id = 2のアイテムの名前と値のアイテムを更新するとします。

私はマングースと一緒に以下を試しました:

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

このアプローチの問題は、オブジェクト全体を更新/設定することです。したがって、この場合、idフィールドが失われます。

マングースで配列に特定の値を設定し、他の値はそのままにしておくより良い方法はありますか?

私はまた、人だけを尋ねました:

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

回答:


162

あなたは近くにいます。これを行うには、$更新演算子の使用にドット表記を使用する必要があります。

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

こんにちは、私が正確に行うとき、あなたは提案しました。board.update({_ id:board._id、 "users.username":req.user.username}、{$ set:{"users。$。lastViewed":new Date()}}、function(err){} ); エラーが発生しました:パーツ(users.usernameのusers)を使用して要素をトラバースできません({users:[{username: "nlm"、_ id:ObjectId( '583c8cc3813daa6c29f69cb0')、status: "invited"、role: "レビュアー "}]})。私が違うことをしたことはありますか?
Peter Huang

4
これはうまくいきます、ありがとう。ただし、配列にない場合にアイテムを作成する方法はありますか?
Sergey Mell 2017年

@SergeyMell私はそれが解決策になるかもしれないと思う場合:stackoverflow.com/a/33577318/6470918
グジェゴシBrzęczyszczykiewicz

コレクション内のすべてのドキュメントでid = 2の名前を更新するにはどうすればよいですか?
ロッド

1
配列内にオブジェクトの配列がある場合、これはどのように機能しますか?ただの代わりにitems.$.name、あなたは持っていましたitems.users.$.statusか?それはうまくいくでしょうか?
スティーヴィースター


11

それを行うにはマングースの方法があります。

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

5

ドキュメントごとに、更新演算子$set複数の値設定できるため、items配列内のオブジェクト全体を置き換えるのではなく、オブジェクトのフィールドnamevalueフィールドを個別に設定できます。

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

3

複数の条件に基づいて配列内のオブジェクトを検索する場合は、$ elemMatchを使用することを覚えておく必要があります。

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

ここにドキュメントがあります



1

以下は、オブジェクトの配列の値をより動的に更新する方法の例です。

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

このようにすることで、次のarrayFiltersように追加することで、ネストされた配列のさらに深いレベルを更新できることに注意してください。

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

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

お役に立てば幸いです。幸運を!


0

マングースでは、単純な配列のように更新できます

user.updateInfoByIndex(0,"test")

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

4
あなたの答えは、いくつかの説明でより役立つでしょう。編集をご検討ください。
O.ジョーンズ

0

マングースでは、次の方法で、$set内部のdot(.)表記を使用して配列値を特定の値に更新できます。

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

説明付きの回答を編集しますか、それとも質問に関連しますか?
NIKHIL CM 2017

1
あなたは、おそらく私の質問を見てみることができ、マングースは使用しています私のクエリの一部を除去している$ []それは、CLIで動作していてもstackoverflow.com/questions/64223672/...
nrmad

0

うまく機能する他の解決策を試しましたが、彼らの答えの落とし穴は、既存のフィールドだけが更新され、それにアップサートを追加しても何も起こらないということです。そこで私はこれを思いつきました。

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.