2013-02-06 24 views
8

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

{ 
"_id" : ObjectId(), 
"post" : "", 
"comments" : [ 
     { 
       "user" : "test", 
       "avatar" : "/static/avatars/asd.jpg", 
       "text" : "....." 
     } 
     { 
       "user" : "test", 
       "avatar" : "/static/avatars/asd.jpg", 
       "text" : "....." 
     } 
     { 
       "user" : "test", 
       "avatar" : "/static/avatars/asd.jpg", 
       "text" : "....." 
     } 
     ... 
    ] 
} 

मैं निम्न क्वेरी निष्पादित करने के लिए कोशिश कर रहा हूँ: मैं इस तरह संरचना मिला

update({"comments.user":"test"},{$set:{"comments.$.avatar": "new_avatar.jpg"}},false,true) 

समस्या यह है कि यह सभी दस्तावेजों को अद्यतन, लेकिन यह हर में केवल प्रथम श्रेणी घटकों को अद्यतन है दस्तावेज़। क्या सभी सरणी तत्वों को अद्यतन करने का कोई तरीका है या मुझे इसे मैन्युअल रूप से करने का प्रयास करना चाहिए? धन्यवाद।

उत्तर

19

आप एकल अद्यतन ऑपरेशन में एकाधिक सरणी तत्वों को संशोधित नहीं कर सकते हैं। इस प्रकार, आपको उन दस्तावेज़ों को माइग्रेट करने के लिए अद्यतन दोहराना होगा जिन्हें संशोधित करने के लिए एकाधिक सरणी तत्वों की आवश्यकता होती है। आप प्रत्येक दस्तावेज के माध्यम से पुनरावृत्ति संग्रह में, बार बार दस्तावेज़ तक $elemMatch के साथ एक अपडेट लागू करके ऐसा कर सकते हैं उसके प्रासंगिक टिप्पणियां के सभी जगह ले ली है, जैसे:

 
db.collection.find().forEach(function(doc) { 
    do { 
    db.collection.update({_id: doc._id, 
          comments:{$elemMatch:{user:"test", 
               avatar:{$ne:"new_avatar.jpg"}}}}, 
         {$set:{"comments.$.avatar":"new_avatar.jpg"}}); 
    } while (db.getPrevError().n != 0); 
}) 

ध्यान दें कि यदि इस आपरेशन की दक्षता के लिए एक आवश्यकता है आपका आवेदन, आपको अपनी स्कीमा को सामान्य बनाना चाहिए ताकि उपयोगकर्ता के अवतार का स्थान प्रत्येक टिप्पणी के बजाए एक दस्तावेज़ में संग्रहीत किया जा सके।

+0

उत्तर के लिए धन्यवाद। ठीक है चूंकि मोंगो शामिल नहीं होता है, इसलिए मैं ब्लॉग सिस्टम को टिप्पणियों के साथ बनाना चाहता हूं, और मैं अपनी टिप्पणियों के बगल में हर उपयोगकर्ता अवतार दिखाना चाहता हूं। कोई सुझाव है कि मैं अपनी स्कीमा कैसे बनाऊं? –

+0

संकल्पनात्मक रूप से, आपको किसी उपयोगकर्ता => अवतार मानचित्र को कहीं भी स्टोर करना होगा। आप उपयोगकर्ता दस्तावेज़ में अपने उपयोगकर्ता के अवतार को स्टोर कर सकते हैं (आपके उपयोगकर्ता संग्रह में), या आप उस ब्लॉग एंट्री के दस्तावेज़ के किसी दिए गए ब्लॉग एंट्री के टिप्पणीकर्ताओं के लिए उपयोगकर्ता => अवतार मानचित्र स्टोर कर सकते हैं। MongoDB में सामान्यीकरण के हल्के उपचार के लिए http://docs.mongodb.org/manual/applications/database-references/ देखें, और http://docs.mongodb.org/manual/use-cases/storing-comments/ के लिए एक "उपयोगकर्ता टिप्पणियां" केस विश्लेषण का उपयोग करें। –

+0

हाँ, मैंने आपके उत्तर को देखने से ठीक पहले उस समाधान को समझ लिया। वैसे भी आपको बहुत धन्यवाद @ जेसन। –

5

एक समाधान प्रत्येक के लिए उपयोग करने के लिए एक फ़ंक्शन बना सकता है और इसे विकसित कर रहा है (इसलिए यह जल्दी से चलता है)। अपने संग्रह को मानना ​​"लेख" है, आप निम्न को चला सकते हैं:

var runUpdate = function(){ 
    db.article.find({"comments.user":"test").forEach(function(article) { 
     for(var i in article.comments){ 
      article.comments[i].avatar = 'new_avatar.jpg'; 
     } 
     db.article.save(article); 
    }); 
}; 

db.eval(runUpdate); 
-1

ऐसा लगता है कि आप यह कर सकते हैं:

db.yourCollection.update({"comments.user":"test"},{$set:{"comments.0.avatar": "new_avatar.jpg", "comments.1.avatar": "new_avatar.jpg", etc...}) 

तो अगर आप सरणी तत्वों के एक छोटे से ज्ञात नंबर है, यह करने के लिए थोड़ा आसान हो सकता है। यदि आप कुछ "टिप्पणियां * * अवतार" चाहते हैं - यह सुनिश्चित न करें कि यह कैसे करें। यह शायद है कि अच्छा आप इतना डेटा दोहराव यद्यपि है कि नहीं है ..

1

आप अनुक्रमित जानते हैं कि आप अद्यतन करने के लिए आप इस तरह कोई समस्या नहीं के साथ ऐसा कर सकते हैं:

var update = { $set: {} }; 
for (var i = 0; i < indexesToUpdate.length; ++i) { 
    update.$set[`comments.${indexesToUpdate[i]}. avatar`] = "new_avatar.jpg"; 
} 
Comments.update({ "comments.user":"test" }, update, function(error) { 
    // ... 
}); 
  • बारे में पता होना आईडीई के सिंटैक्स को स्वीकार नहीं किया जाएगा, लेकिन आप इसे अनदेखा कर सकते हैं।