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


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.