Mongoose, ऑब्जेक्ट की सरणी में मानों को अपडेट करें


101

क्या किसी वस्तु में मूल्यों को अद्यतन करने का एक तरीका है?

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

आइए कहते हैं कि मैं उस आइटम के लिए नाम और मूल्य आइटम को अपडेट करना चाहता हूं जहां आईडी = 2;

मैंने निम्नलिखित w / mongoose की कोशिश की है:

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

इस दृष्टिकोण के साथ समस्या यह है कि यह संपूर्ण ऑब्जेक्ट को अपडेट / सेट करता है, इसलिए इस मामले में मैं आईडी फ़ील्ड खो देता हूं।

क्या किसी निश्चित मान को सरणी में सेट करने के लिए मानगो में बेहतर तरीका है लेकिन अन्य मूल्यों को अकेला छोड़ दें?

मैं भी सिर्फ व्यक्ति के लिए queried है:

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

जवाबों:


169

तुम पास हो; आपको ऐसा करने के लिए $अद्यतन ऑपरेटर के अपने उपयोग में डॉट नोटेशन का उपयोग करना चाहिए :

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 (ग़लती) {} ); मुझे एक त्रुटि मिली: तत्व ({users: [{username: "nlm", _id: ObjectId ('583c8cc3813daa6a29f69cb0'), स्थिति: "आमंत्रित", भूमिका: "तत्व () (उपयोगकर्ता नाम: उपयोगकर्ता नाम) का उपयोग नहीं कर सकते। समीक्षक "}]})। क्या मैंने कुछ अलग किया है?
पीटर हुआंग

6
यह बहुत अच्छा काम करता है, धन्यवाद। हालाँकि, क्या कोई ऐसा आइटम बनाने का कोई तरीका है, अगर वह सरणी में नहीं है?
सर्गेई मेल

@ SergeyMell अगर मुझे लगता है कि एक समाधान हो सकता है: stackoverflow.com/a/33577318/6470918
Grzegorz Brzęczyszczykiewicz

मैं एक संग्रह में सभी दस्तावेजों में आईडी = 2 के लिए नाम कैसे अपडेट करूं?
रॉड

1
यदि आपके पास किसी सरणी के अंदर वस्तुओं की एक सरणी है तो यह कैसे काम करेगा? बस के बजाय की तरह items.$.name, आप था items.users.$.status? क्या इससे काम हो जायेगा?
स्टेवी स्टार


14

इसे करने के लिए एक सामान्य तरीका है।

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सरणी, आप सेट कर सकते हैं nameऔर valueव्यक्तिगत रूप से वस्तु के क्षेत्र।

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

5

याद करने के लिए एक बात है, जब आप एक से अधिक स्थिति के आधार पर सरणी में ऑब्जेक्ट खोज रहे हैं तो $ एलएमएमच का उपयोग करें

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

यहाँ डॉक्स है


4

नीचे एक उदाहरण है कि वस्तुओं के सरणी में मूल्य को और अधिक गतिशील रूप से कैसे अपडेट किया जाए।

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
आपका उत्तर कुछ स्पष्टीकरण के साथ अधिक सहायक होगा। कृपया इसे संपादित करने पर विचार करें।
ओ। जोन्स

0

Mongoose में, हम निम्नलिखित तरीके से विशिष्ट मूल्य के लिए $setडॉट ( .) नोटेशन का उपयोग करके सरणी मान को अपडेट कर सकते हैं

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

क्या आप स्पष्टीकरण के साथ उत्तर संपादित करेंगे, या प्रश्न से संबंधित होंगे?
NIKHIL CM

1
आप संभवतः मेरे सवाल पर एक नज़र ले सकता है, नेवला अपनी क्वेरी का हिस्सा है जो का उपयोग करता है को हटा रहा है $ [] भले ही यह CLI में काम करता है stackoverflow.com/questions/64223672/...
nrmad

0

अन्य समाधानों की कोशिश करने के बाद, जो ठीक काम करते हैं, लेकिन उनके जवाबों का नुकसान यह है कि केवल पहले से मौजूद क्षेत्र अद्यतन करने के लिए इसे जोड़ने के लिए कुछ भी नहीं करेंगे, इसलिए मैं इसके साथ आया।

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

0

मेरे पास इसी तरह के मुद्दे थे। यहाँ यह करने का सबसे साफ तरीका है।

    const personQuery = {
       _id: 1  
    }

    const itemID = 2;

    Person.findOne(personQuery).then(item => {
       const audioIndex = item.items.map(item => item.id).indexOf(itemID);
       item.items[audioIndex].name = 'Name value';
       item.save();
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.