2010-10-25 7 views
91

मैं एक दस्तावेज़ के _id MongoDB को अपडेट करना चाहता हूं। मुझे पता है कि यह वास्तव में एक अच्छा pratice नहीं है। लेकिन कुछ तकनीकी कारणों से, मुझे इसे अपडेट करने की आवश्यकता है। लेकिन अगर मैं इसे अद्यतन करने का प्रयास करता हूं तो मेरे पास है:एक मोंगोडीबी दस्तावेज़ के _id को कैसे अपडेट करें?

> db.clients.update({'_id':ObjectId("4cc45467c55f4d2d2a000002")}, {'$set':{'_id':ObjectId("4c8a331bda76c559ef000004")}}); 
Mod on _id not allowed 

और अद्यतन नहीं किया गया है। मैं वास्तव में इसे कैसे अपडेट कर सकता हूं?

उत्तर

152

आप इसे अपडेट नहीं कर सकते हैं। आपको एक नया _id का उपयोग करके दस्तावेज़ को सहेजना होगा, और फिर पुराने दस्तावेज़ को हटा दें।

// store the document in a variable 
doc = db.clients.findOne({_id: ObjectId("4cc45467c55f4d2d2a000002")}) 

// set a new _id on the document 
doc._id = ObjectId("4c8a331bda76c559ef000004") 

// insert the document, using the new _id 
db.clients.insert(doc) 

// remove the document with the old _id 
db.clients.remove({_id: ObjectId("4cc45467c55f4d2d2a000002")}) 
+18

इस के साथ एक मजेदार समस्या तब दिखाई देती है जब उस दस्तावेज़ के कुछ फ़ील्ड में एक अद्वितीय अनुक्रमणिका हो। उस स्थिति में, आपका उदाहरण विफल हो जाएगा क्योंकि किसी दस्तावेज़ को एक अद्वितीय अनुक्रमित फ़ील्ड में डुप्लिकेट मान के साथ सम्मिलित नहीं किया जा सकता है। आप पहले इसे हटाकर इसे ठीक कर सकते हैं, लेकिन यह एक बुरा विचार है क्योंकि यदि आपका सम्मिलन किसी कारण से विफल रहता है तो आपका डेटा अब खो गया है। आपको इसके बजाय अपना इंडेक्स ड्रॉप करना होगा, काम करना होगा, फिर इंडेक्स को पुनर्स्थापित करना होगा। – skelly

+0

अच्छा बिंदु @skelly! मैं इसी तरह की समस्याओं के बारे में सोचने लगा और 2 घंटे पहले अपनी ताजा टिप्पणी देखी। तो इस संशोधित आईडी परेशानी को उपयोगकर्ता को आईडी चुनने की अनुमति देकर आंतरिक समस्या के रूप में माना जाता है? – RayLuo

+0

यदि आपको 'डालने' रेखा में 'डुप्लिकेट कुंजी त्रुटि' मिलती है और @skelly की समस्या के बारे में चिंतित नहीं हैं, तो सबसे आसान समाधान केवल 'निकालना' पंक्ति को कॉल करना है और फिर 'डालने' पंक्ति को कॉल करना है। 'दस्तावेज़' को पहले से ही आपकी स्क्रीन पर मुद्रित किया जाना चाहिए ताकि सरल दस्तावेजों के लिए, डालने में विफल होने पर भी सबसे खराब मामला पुनर्प्राप्त करना आसान हो। – philfreo

22

आप भी एक पाश का उपयोग कर सकते अपने पूरे संग्रह के लिए यह ऐसा करने के लिए (नील्स उदाहरण के आधार पर):

db.status.find().forEach(function(doc){ 
    doc._id=doc.UserId; db.status_new.insert(doc); 
}); 
db.status_new.renameCollection("status", true); 

इस मामले UserId में नया आईडी मैं

+1

क्या स्नैपशॉट() को सलाह दी जाएगी कि प्रत्येक को गलती से नए दस्तावेज़ों को चुनने से रोकने के लिए सलाह दी जाए? –

+0

यह कोड स्निपेट कभी पूरा नहीं होता है। यह हमेशा के लिए संग्रह पर और अधिक रखता रहता है। स्नैपशॉट वह नहीं करता जो आप उम्मीद करते हैं (आप संग्रह में दस्तावेज़ जोड़ने के लिए 'स्नैपशॉट' ले कर इसका परीक्षण कर सकते हैं, फिर यह देखकर कि नया दस्तावेज़ स्नैपशॉट में है) – Patrick

+0

देखें http://stackoverflow.com/a/28083980 स्नैपशॉट के विकल्प के लिए/305324।'सूची() 'तार्किक है, लेकिन बड़े डेटाबेस के लिए यह स्मृति – Patrick

0

उपयोग करना चाहता था था मामले में, आप (उदाहरण के लिए, यदि आप कुछ _ids उपसर्ग करना चाहते हैं) एक ही संग्रह में _ id नाम बदलना चाहते हैं:

db.someCollection.find().snapshot().forEach(function(doc) { 
    if (doc._id.indexOf("2019:") != 0) { 
     print("Processing: " + doc._id); 
     var oldDocId = doc._id; 
     doc._id = "2019:" + doc._id; 
     db.someCollection.insert(doc); 
     db.someCollection.remove({_id: oldDocId}); 
    } 
}); 

अगर (doc._id.indexOf ("201 9:")! = 0) {... अनंत लूप को रोकने के लिए आवश्यक है, क्योंकि प्रत्येक के माध्यम से सम्मिलित दस्तावेज़ों को भी चुनता है। स्नैपशॉट() विधि का उपयोग किया जाता है।

संबंधित मुद्दे