फ़ील्ड का प्रकार कैसे बदलें?


158

मैं मानगो शेल के भीतर से एक क्षेत्र के प्रकार को बदलने की कोशिश कर रहा हूं।

मैं यह कर रहा हूँ ...

db.meta.update(
  {'fields.properties.default': { $type : 1 }}, 
  {'fields.properties.default': { $type : 2 }}
)

लेकिन यह काम नहीं कर रहा है!


अगर कोई भी उसी स्थिति में है, जो toStringकिसी दस्तावेज़ के क्षेत्र में है, तो यहाँ पर जो छोटा कार्यक्रम मैंने बनाया / उपयोग किया है, वह है
talles

जवाबों:


213

एक ही रास्ता बदलने के लिए $type डेटा के डेटा जहां डाटा सही प्रकार है पर एक अद्यतन प्रदर्शन करने के लिए है।

इस मामले में, ऐसा लगता है कि आप $type 1 (डबल) से 2 (स्ट्रिंग) को बदलने की कोशिश कर रहे हैं ।

तो बस दस्तावेज़ को DB से लोड करें, कलाकारों को प्रदर्शन करें ( new String(x)) और फिर दस्तावेज़ को फिर से सहेजें।

यदि आपको इसे प्रोग्रामेटिक और पूरी तरह से शेल से करने की आवश्यकता है, तो आप find(...).forEach(function(x) {})सिंटैक्स का उपयोग कर सकते हैं ।


नीचे की दूसरी टिप्पणी के जवाब में। badसंग्रह में संख्या से स्ट्रिंग तक फ़ील्ड बदलें foo

db.foo.find( { 'bad' : { $type : 1 } } ).forEach( function (x) {   
  x.bad = new String(x.bad); // convert field to string
  db.foo.save(x);
});

1
उदाहरण का कोई भी मौका - एक फ़ील्ड प्रकार को इंट से स्ट्रिंग (या इसके विपरीत), शेल से बदलना?
एलिस्टर बुलमैन

30
Int32-> स्ट्रिंग के मामले में, new String(x.bad)0-सूचकांक-आइटम x.badमूल्य के साथ स्ट्रिंग्स का संग्रह बनाता है । संस्करण ""+x.bad, सिमोन द्वारा वर्णित काम करता है के रूप में वांछित - Int32 के बजाय स्ट्रिंग मान बनाता है
दाव

उपरोक्त कोड फ़ील्ड डेटा को डबल से स्ट्रिंग के बजाय डबल से एरे में परिवर्तित कर रहा है। मेरा वास्तविक डेटा इस प्रारूप में था: 3.1 जबकि सिमोन कोड मेरे लिए ठीक काम कर रहा है
पंकज खुराना

2
एक ऐसी स्थिति थी जहाँ मुझे _id फ़ील्ड को परिवर्तित करने की आवश्यकता थी और साथ ही साथ अन्य अनुक्रमणिकाओं के साथ संघर्ष नहीं:db.questions.find({_id:{$type:16}}).forEach( function (x) { db.questions.remove({_id:x._id},true); x._id = ""+x._id; db.questions.save(x); });
मैट मोलनार

@SundarBons हाँ आप अपने डेटाबेस में एक क्षेत्र को फिर से लिख रहे हैं, यह एक बड़ी बात है कि आप इसे कैसे करते हैं। यदि आप SQL का उपयोग कर रहे थे और यह एक बड़ी तालिका थी, तो आपको शायद कुछ समय कम लेना होगा।
गेट्स वीपी

161

स्ट्रिंग फ़ील्ड को पूर्णांक में बदलें:

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) { 
    obj.field-name = new NumberInt(obj.field-name);
    db.db-name.save(obj);
});

पूर्णांक फ़ील्ड को स्ट्रिंग में परिवर्तित करें:

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
    obj.field-name = "" + obj.field-name;
    db.db-name.save(obj);
});

यह बहुत अच्छा है - क्या आप जानते हैं कि आप एक स्ट्रिंग कैसे बदलेंगे (सोचें '1.23' जैसी मुद्रा) पूर्णांक 123 में? मुझे लगता है कि आपको इसे फ्लोट या दशमलव के रूप में पार्स करना होगा, इसे 100 से गुणा करें, फिर इसे पूर्णांक के रूप में सहेजें, लेकिन मुझे ऐसा करने के लिए सही डॉक्स नहीं मिलेंगे। धन्यवाद!
ब्रायन आर्मस्ट्रांग

वास्तव में यह काम अच्छा है। लेकिन मेरे पास एक एप्लिकेशन है जो मोंगॉयड 2.4.0-स्थिर के साथ चल रहा है जिसमें फ़ील्ड जैसे फ़ील्ड हैं: customer_count, टाइप: Integer & a validation as validates_numericality_of: customer_count जो ठीक काम कर रहा था। अब जब मैं ३.१.१६ को मूंगॉइड में अपग्रेड कर रहा हूं, जब मैं एक स्ट्रिंग मान असाइन करता हूं तो यह स्वतः ही इसे ०.० में बदल देता है। मैं गलत डेटा असाइनमेंट पर एक त्रुटि फेंकना चाहता हूं, यह व्यवहार मेरे लिए अजीब है।
स्वप्निल चिंचोलकर

4
मैंने इसे चलाया और त्रुटि मिली: त्रुटि: स्ट्रिंग को पूर्णांक (शेल) में परिवर्तित नहीं कर सकी: 1
Mittenchops

और अगर आपको स्ट्रिंग (या "सामान्य" 32-बिट पूर्णांक) को 64-बिट पूर्णांक में बदलने की आवश्यकता है, तो NumberLongयहां उपयोग करें:db.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
boryn

इसका काम ठीक है। क्या मुझे पता है कि एम्बेड किए गए दस्तावेज़ फ़ील्ड के भीतर डेटाटाइप को कैसे बदलना है
संकर् मुनियप्पा

43

स्ट्रिंग टू इंट रूपांतरण।

db.my_collection.find().forEach( function(obj) {
    obj.my_value= new NumberInt(obj.my_value);
    db.my_collection.save(obj);
});

स्ट्रिंग टू डबल रूपांतरण के लिए।

    obj.my_value= parseInt(obj.my_value, 10);

फ्लोट के लिए:

    obj.my_value= parseFloat(obj.my_value);

2
मैं यह भी निर्दिष्ट करने की सलाह दूंगा radix- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Russ Cam

5
बाहर देखो , मैंने रोबोमोंगो के साथ इसका परीक्षण किया, और इसके परिणामस्वरूप टाइप 1: डबल हुआ। का उपयोग करना थाnew NumberInt()
डैनियल एफ

डैनियल, उर समाधान ठीक नहीं है ... दाविद का समाधान ठीक है
राजीब

22
db.coll.find().forEach(function(data) {
    db.coll.update({_id:data._id},{$set:{myfield:parseInt(data.myfield)}});
})

15

शुरू करना Mongo 4.2, db.collection.update()एक एकत्रीकरण पाइपलाइन को स्वीकार कर सकता है, अंत में अपने स्वयं के मूल्य के आधार पर एक क्षेत्र के अद्यतन की अनुमति देता है:

// { a: "45", b: "x" }
// { a:  53,  b: "y" }
db.collection.update(
  { a : { $type: 1 } },
  [{ $set: { a: { $toString: "$a" } } }],
  { multi: true }
)
// { a: "45", b: "x" }
// { a: "53", b: "y" }
  • पहला भाग { a : { $type: 1 } }मैच क्वेरी है:

    • यह फ़िल्टर करता है कि कौन से दस्तावेज़ अपडेट करने हैं।
    • इस मामले में, चूंकि हम "a"स्ट्रिंग को परिवर्तित करना चाहते हैं जब इसका मूल्य एक डबल है, तो यह उन तत्वों से मेल खाता है जिनके लिए "a"यह प्रकार का है1 (डबल) है।
    • यह तालिका विभिन्न प्रकार के संभावित कोड का प्रतिनिधित्व करती है।
  • दूसरा भाग [{ $set: { a: { $toString: "$a" } } }]अद्यतन एकत्रीकरण पाइपलाइन है:

    • ध्यान दें कि यह अद्यतन क्वेरी एक एकत्रीकरण पाइपलाइन का उपयोग करती है, यह इंगित करते हुए वर्ग कोष्ठक पर ध्यान दें।
    • $set एक नया एकत्रीकरण ऑपरेटर है (Mongo 4.2 ) है जो इस मामले में एक क्षेत्र को संशोधित करता है।
    • यह केवल के रूप में पढ़ा जा सकता है "$set"के मान "a"को "$a"परिवर्तित"$toString"
    • यहां वास्तव में नया क्या है, Mongo 4.2इसे अपडेट करते समय दस्तावेज़ को स्वयं संदर्भित करने में सक्षम किया जा रहा है: के लिए नया मान "a"मौजूदा मूल्य पर आधारित है"$a"
    • यह भी ध्यान दें "$toString"कि एक नया एकत्रीकरण ऑपरेटर कौन सा है Mongo 4.0
  • मत भूलो { multi: true }, अन्यथा केवल पहला मिलान दस्तावेज़ अपडेट किया जाएगा।


यदि आपका कास्ट डबल से स्ट्रिंग में नहीं है, तो आपके पास अलग-अलग रूपांतरण ऑपरेटरों के बीच पसंद है , Mongo 4.0जैसे कि $toBool,$toInt ...

और अगर आपके लक्षित प्रकार के लिए एक समर्पित कनवर्टर नहीं है, तो आप { $toString: "$a" }एक $convertऑपरेशन से बदल सकते हैं : { $convert: { input: "$a", to: 2 } }जहां के लिए मूल्य toइस तालिका में पाया जा सकता है :

db.collection.update(
  { a : { $type: 1 } },
  [{ $set: { a: { $convert: { input: "$a", to: 2 } } } }],
  { multi: true }
)

1
db.collection.updateMany( { a : { $type: 1 } }, [{ $set: { a: { $toString: "$a" } } }] )- का multi : trueउपयोग करने से बचा जा सकता हैupdateMany
वसीम

1
2020 तक, $ कन्वर्ट का उपयोग इसके लिए सही तरीका होना चाहिए क्योंकि यह बहुत अधिक कुशल होना चाहिए (और बूट करने के लिए उपयोग करना आसान है)।
खलीलरावण

10

सभी उत्तर अब तक सभी संस्करण तत्वों के क्लाइंट-साइड पर पुनरावृति करते हुए कुछ संस्करण का उपयोग करते हैं।

हालाँकि, आप समग्र पाइपलाइन और $ आउट स्टेज का उपयोग करके MongoDB के सर्वर-साइड प्रसंस्करण का उपयोग कर सकते हैं :

$ आउट स्टेज एटोमिकली नए परिणाम संग्रह के साथ मौजूदा संग्रह को बदल देती है।

उदाहरण:

db.documents.aggregate([
         {
            $project: {
               _id: 1,
               numberField: { $substr: ['$numberField', 0, -1] },
               otherField: 1,
               differentField: 1,
               anotherfield: 1,
               needolistAllFieldsHere: 1
            },
         },
         {
            $out: 'documents',
         },
      ]);

2
मुझे नहीं पता कि यह अधिक क्यों नहीं उतारा जाता है। बड़े डेटा सेट पर पंक्ति संचालन द्वारा पंक्ति प्रदर्शन पर हत्या कर रहे हैं
अल्फ

7

स्ट्रिंग प्रकार के फ़ील्ड को दिनांक फ़ील्ड में बदलने के लिए, आपको find()विधि का उपयोग करके लौटे कर्सर को पुनरावृत्त करना होगा forEach(), लूप के भीतर फ़ील्ड को दिनांक ऑब्जेक्ट में परिवर्तित करें और फिर फ़ील्ड का उपयोग करके अपडेट करें$set ऑपरेटर ।

बल्क एपीआई का उपयोग करके लाभ उठाएंबल्क अपडेट के लिए जो बेहतर प्रदर्शन की पेशकश करते हैं क्योंकि आप सर्वर को ऑपरेशन को 1000 के बैचों में भेज रहे हैं जो आपको बेहतर प्रदर्शन देता है क्योंकि आप सर्वर को हर अनुरोध नहीं भेज रहे हैं, बस एक बार हर में 1000 अनुरोध

निम्नलिखित इस दृष्टिकोण को प्रदर्शित करता है, पहला उदाहरण MongoDB संस्करणों में उपलब्ध बल्क एपीआई का उपयोग करता है >= 2.6 and < 3.2। यह सभी created_atफ़ील्ड्स को दिनांक फ़ील्ड में परिवर्तित करके संग्रह के सभी दस्तावेज़ों को अपडेट करता है :

var bulk = db.collection.initializeUnorderedBulkOp(),
    counter = 0;

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
    var newDate = new Date(doc.created_at);
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "created_at": newDate}
    });

    counter++;
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.collection.initializeUnorderedBulkOp();
    }
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }

अगला उदाहरण नए MongoDB संस्करण पर लागू होता है, 3.2जिसने तब से Bulk API को अपदस्थ कर दिया है और इसमें एपिस का नया सेट प्रदान किया गया है bulkWrite():

var bulkOps = [];

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) { 
    var newDate = new Date(doc.created_at);
    bulkOps.push(         
        { 
            "updateOne": { 
                "filter": { "_id": doc._id } ,              
                "update": { "$set": { "created_at": newDate } } 
            }         
        }           
    );     
})

db.collection.bulkWrite(bulkOps, { "ordered": true });

1
महान जवाब, बल्क विधि मेरे लिए लगभग 100x तेज चलती है, भले ही यह अभी भी एक तुल्यकालिक कॉल प्रतीत होता है।
मैथ्यू पढ़ें

3

Int32 को स्ट्रिंग में बदलने के लिए मोंगो में एक सरणी बनाए बिना बस "" को अपनी संख्या में जोड़ें :-)

db.foo.find( { 'mynum' : { $type : 16 } } ).forEach( function (x) {   
  x.mynum = x.mynum + ""; // convert int32 to string
  db.foo.save(x);
});

3

वास्तव में मोंडोबीडी में वस्तु के प्रकार को बदलने में मुझे क्या मदद मिली, यह सिर्फ सरल रेखा थी, शायद यहां पहले उल्लेख किया गया है: ...

db.Users.find({age: {$exists: true}}).forEach(function(obj) {
    obj.age = new NumberInt(obj.age);
    db.Users.save(obj);
});

उपयोगकर्ता मेरा संग्रह हैं और उम्र वह वस्तु है जिसमें पूर्णांक (int32) के बजाय एक स्ट्रिंग थी।


1

मुझे संग्रह में कई क्षेत्रों के डेटाटाइप को बदलने की आवश्यकता है, इसलिए मैंने दस्तावेजों के संग्रह में कई डेटा प्रकार परिवर्तन करने के लिए निम्नलिखित का उपयोग किया। किसी पुराने प्रश्न का उत्तर दें लेकिन दूसरों के लिए मददगार हो सकता है।

db.mycoll.find().forEach(function(obj) { 

    if (obj.hasOwnProperty('phone')) {
        obj.phone = "" + obj.phone;  // int or longint to string
    }

    if (obj.hasOwnProperty('field-name')) {
     obj.field-name = new NumberInt(obj.field-name); //string to integer
    }

    if (obj.hasOwnProperty('cdate')) {
        obj.cdate = new ISODate(obj.cdate); //string to Date
    }

    db.mycoll.save(obj); 
});

1
You can easily convert the string data type to numerical data type.
Don't forget to change collectionName & FieldName.
for ex : CollectionNmae : Users & FieldName : Contactno.

इस क्वेरी को आज़माएं ..

db.collectionName.find().forEach( function (x) {
x.FieldName = parseInt(x.FieldName);
db.collectionName.save(x);
});

1

डेमो परिवर्तन स्ट्रिंग से mongo objectId के लिए मोंगोज़ का उपयोग करके मध्य क्षेत्र का प्रकार

 Post.find({}, {mid: 1,_id:1}).exec(function (err, doc) {
             doc.map((item, key) => {
                Post.findByIdAndUpdate({_id:item._id},{$set:{mid: mongoose.Types.ObjectId(item.mid)}}).exec((err,res)=>{
                    if(err) throw err;
                    reply(res);
                });
            });
        });

Mongo ObjectId ऐसी शैलियों का एक और उदाहरण है

संख्या, स्ट्रिंग, बूलियन जो उम्मीद करते हैं कि उत्तर किसी और की मदद करेगा।


0

मैं इस स्क्रिप्ट का उपयोग मोंगोडब कंसोल में स्ट्रिंग के लिए रूपांतरण फ्लोट करने के लिए करता हूं ...

db.documents.find({ 'fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.fwtweaeeba = parseFloat( obj.fwtweaeeba ); 
        db.documents.save(obj); } );    

db.documents.find({ 'versions.0.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[0].content.fwtweaeeba = parseFloat( obj.versions[0].content.fwtweaeeba ); 
        db.documents.save(obj); } );

db.documents.find({ 'versions.1.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[1].content.fwtweaeeba = parseFloat( obj.versions[1].content.fwtweaeeba );  
        db.documents.save(obj); } );

db.documents.find({ 'versions.2.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[2].content.fwtweaeeba = parseFloat( obj.versions[2].content.fwtweaeeba );  
        db.documents.save(obj); } );

और यह एक php में)))

foreach($db->documents->find(array("type" => "chair")) as $document){
    $db->documents->update(
        array('_id' => $document[_id]),
        array(
            '$set' => array(
                'versions.0.content.axdducvoxb' => (float)$document['versions'][0]['content']['axdducvoxb'],
                'versions.1.content.axdducvoxb' => (float)$document['versions'][1]['content']['axdducvoxb'],
                'versions.2.content.axdducvoxb' => (float)$document['versions'][2]['content']['axdducvoxb'],
                'axdducvoxb' => (float)$document['axdducvoxb']
            )
        ),
        array('$multi' => true)
    );


}

0

मेरे मामले में, मैं निम्नलिखित का उपयोग करता हूं

function updateToSting(){
  var collection = "<COLLECTION-NAME>";
  db.collection(collection).find().forEach(function(obj) {
    db.collection(collection).updateOne({YOUR_CONDITIONAL_FIELD:obj.YOUR_CONDITIONAL_FIELD},{$set:{YOUR_FIELD:""+obj.YOUR_FIELD}});
  });
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.