필드 유형을 변경하는 방법은 무엇입니까?


158

mongo 셸 내에서 필드 유형을 변경하려고합니다.

나는 이것을하고있다 ...

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

그러나 작동하지 않습니다!


누군가 내가 같은 상황에 처해 toString있고 문서의 일부를 가지고 있다면 내가 만든 작은 프로그램이 있습니다.
Talls

답변:


213

$type데이터 를 변경하는 유일한 방법 은 데이터의 유형이 올바른 데이터를 업데이트하는 것입니다.

이 경우 $type 1 (double)에서 2 (string) 로 변경하려고하는 것 같습니다 .

따라서 DB에서 문서를로드하고 캐스트 ( new String(x))를 수행 한 다음 문서를 다시 저장하십시오.

프로그래밍 방식으로 완전히 쉘에서이 작업을 수행해야하는 경우 find(...).forEach(function(x) {})구문을 사용할 수 있습니다 .


아래 두 번째 의견에 대한 답변. 필드 bad를 collection의 숫자에서 문자열로 변경하십시오 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
쉘에서 필드 유형을 int에서 string으로 또는 그 반대로 변경하는 예가 있습니까?
Alister Bulman

30
Int32-> String 인 경우 new String(x.bad)0-index-item x.bad값을 가진 Strings 컬렉션을 만듭니다 . ""+x.badSimone에 의해 설명 된 변형 은 원하는대로 작동합니다
Dao

위의 코드는 필드 데이터를 double 대신 string 대신 double에서 array로 변환합니다. 실제 데이터는 다음과 같은 형식으로되어 있습니다 : 3.1. simone 코드는 제게 잘 작동합니다
Pankaj Khurana

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을 사용 중이고 이것이 큰 테이블 인 경우 가동 중지 시간이 필요할 수 있습니다.
Gates VP

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을 곱한 다음 정수로 저장해야한다고 가정하지만 올바른 문서를 찾을 수는 없습니다. 감사!
Brian Armstrong

실제로이 작업은 훌륭합니다. 그러나 mongoid 2.4.0-stable로 실행되는 응용 프로그램이 있습니다 : field : customer_count, type : Integer 및 validates_numericality_of : customer_count와 같은 필드가 정상적으로 작동합니다. 이제 mongoid로 3.0.16으로 업그레이드 할 때 문자열 값을 할당하면 오류없이 자동으로 0으로 변환됩니다. 잘못된 데이터 할당에 오류를 던지고 싶습니다.이 동작은 이상합니다.
스왑 닐 친콜 카르

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

잘 작동합니다. 임베디드 문서 필드 내에서 데이터 유형을 변경하는 방법을 알고 싶습니다
sankar muniyappa

43

문자열을 int로 변환합니다.

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/...
러스 캠

5
조심하십시오 , 나는 이것을 Robomongo로 테스트했으며 결과적으로 유형 1이 두 배가되었습니다. 사용했다new NumberInt()
Daniel F

다니엘, 당신의 해결책은 괜찮습니다 ... 데이비드의 해결책은 괜찮습니다
Rajib

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"값이 double 일 때 문자열 로 변환하려고하므로 (double) "a"유형의 요소와 일치합니다 1.
    • 는 가능한 다른 유형을 나타내는 코드를 제공합니다.
  • 두 번째 부분 [{ $set: { a: { $toString: "$a" } } }]은 업데이트 집계 파이프 라인입니다.

    • 이 업데이트 쿼리가 집계 파이프 라인을 사용함을 나타내는 대괄호는주의하십시오.
    • $setMongo 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
Vasim

1
2020 년 현재 $ convert를 사용하는 것이 훨씬 더 효율적이고 부팅하기가 더 쉬워야하기 때문에 올바른 방법이어야합니다.
KhalilRavanna

10

모든 대답은 지금까지 클라이언트 측의 모든 컬렉션 요소를 반복하여 일부 버전의 forEach를 사용합니다.

그러나 집계 파이프 라인 및 $ out 스테이지 를 다음과 같이 사용하여 MongoDB의 서버 측 처리를 사용할 수 있습니다 .

$ out 스테이지는 기존 콜렉션을 새 결과 콜렉션으로 원자 적으로 대체합니다.

예:

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

2
왜 이것이 더 많이지지되지 않는지 모르겠습니다. 대규모 데이터 세트에 대한 행 단위 작업은 성능이 저하됩니다.
Alf47

7

문자열 유형의 필드를 날짜 필드로 변환하려면 find()메소드를 사용하여 forEach()메소드가 리턴 한 커서를 반복 하고 루프 내에서 필드를 Date 오브젝트로 변환 한 다음 $set연산자를 사용하여 필드를 업데이트해야합니다 .

대량 업데이트를 위해 대량 API 를 사용하는 경우 1000 개 단위로 작업을 서버에 보낼 때 더 나은 성능을 제공합니다. 이렇게하면 모든 요청을 서버에 한 번에 하나씩 보내지 않아도 성능이 향상됩니다. 요청 1,000 개

다음은이 접근법을 보여줍니다. 첫 번째 예는 MongoDB 버전에서 사용 가능한 벌크 API를 사용합니다 >= 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이후 한 대량의 API를 사용되지 않는 사용하는 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
큰 대답은 벌크 방법이 여전히 동기 호출 인 것처럼 보이지만 약 100 배 더 빠릅니다.
Matthew 읽기

3

배열을 만들지 않고 mont에서 int32를 문자열로 변환하려면 숫자에 ""를 추가하십시오 :-)

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

3

MondoDB에서 객체의 유형을 변경하는 데 실제로 도움이 된 것은 아마도 앞에서 언급 한 간단한 줄이었습니다.

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

mongoose를 사용하여 문자열에서 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

mongodb 콘솔 에서이 스크립트를 문자열에서 부동 변환으로 사용합니다 ...

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}});
  });
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.