ChatGPT解决这个技术问题 Extra ChatGPT

如何更改字段的类型?

我正在尝试从 mongo shell 中更改字段的类型。

我正在做这个...

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

但它不工作!

如果有人遇到与我相同的情况,则必须toString某些文档的字段,here's the little program I've made/used

u
user6039980

更改数据 $type 的唯一方法是对数据类型正确的数据执行更新。

在这种情况下,您似乎正在尝试更改 $type from 1 (double) to 2 (string)

因此,只需从数据库加载文档,执行转换 (new String(x)),然后再次保存文档。

如果您需要完全从 shell 以编程方式执行此操作,您可以使用 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);
});

任何机会 - 从外壳将字段类型从 int 更改为 string(反之亦然)?
在 Int32->String 的情况下,new String(x.bad) 创建具有 0-index-item x.bad 值的字符串集合。由 Simone 描述的变体 ""+x.bad 按需要工作 - 创建 String 值而不是 Int32
上面的代码是将字段数据从 double 转换为 array,而不是 double 到 string。我的实际数据采用这种格式:3.1,而 simone 代码对我来说工作正常
有一种情况,我需要转换 _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); });
.save is not a function 面临此错误
Y
Yaroslav Admin

将字符串字段转换为整数:

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,然后将其保存为整数,但我找不到合适的文档来执行此操作。谢谢!
其实这个工作很好。但是我有一个使用 mongoid 2.4.0-stable 运行的应用程序,它具有诸如字段:customer_count、类型:整数和验证为 validates_numericality_of :customer_count 之类的字段,它工作正常。现在,当我将 mongoid 升级到 3.0.16 时,当我分配一个字符串值时,它会自动将其转换为 0。没有错误。我想在错误的数据分配上抛出一个错误,这种行为对我来说很奇怪。
我运行它并得到错误:错误:无法将字符串转换为整数(shell):1
如果您需要将字符串(或“普通”32 位整数)转换为 64 位整数,请在此处使用 NumberLongdb.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
这不仅适用于数字,也适用于 ObjectId 数据类型。
X
Xavier Guihot

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(双精度)的元素。此表提供了代表不同可能类型的代码。

它过滤要更新的文档。

在这种情况下,由于我们希望将“a”的值为双精度值时转换为字符串,这匹配“a”类型为 1(双精度)的元素。

此表提供了代表不同可能类型的代码。

第二部分 [{ $set: { a: { $toString: "$a" } } }] 是更新聚合管道:注意方括号表示此更新查询使用聚合管道。 $set 是一个新的聚合运算符(Mongo 4.2),在这种情况下会修改一个字段。这可以简单地理解为“$set”将“a”的值转换为“$a”转换为“$toString”。这里真正的新功能是在 Mongo 4.2 中能够在更新文档时引用文档本身:“a”的新值基于“$a”的现有值。另请注意“$toString”,它是 Mongo 4.0 中引入的新聚合运算符。

请注意方括号,表示此更新查询使用聚合管道。

$set 是一个新的聚合运算符(Mongo 4.2),在这种情况下会修改一个字段。

这可以简单地理解为“$set”将“a”的值转换为“$a”转换为“$toString”。

这里真正的新功能是在 Mongo 4.2 中能够在更新文档时引用文档本身:“a”的新值基于“$a”的现有值。

另请注意“$toString”,它是 Mongo 4.0 中引入的新聚合运算符。

不要忘记 { multi: true },否则只会更新第一个匹配的文档。

如果您的转换不是从 double 到 string,您可以选择 Mongo 4.0 中引入的不同转换运算符,例如 $toBool$toInt、...

如果没有针对您的目标类型的专用转换器,您可以将 { $toString: "$a" } 替换为 $convert 操作:{ $convert: { input: "$a", to: 2 } } 其中 to 的值可以在此 table 中找到:

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

db.collection.updateMany( { a : { $type: 1 } }, [{ $set: { a: { $toString: "$a" } } }] ) - 使用 updateMany 可以避免 multi : true
截至 2020 年,使用 $convert 应该是正确的方法,因为它应该更有效(并且更易于使用启动)。
从 Mongo 4.0 开始,有速记运算符:“...除了 $convert 之外,当默认的“onError”和“onNull”行为可接受时,MongoDB 还提供以下聚合运算符作为速记”。 mongodb.com/docs/manual/reference/operator/aggregation/convert/…
D
David Dehghan

用于字符串到 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);

小心,我用 Robomongo 对此进行了测试,结果是类型 1:double。必须使用 new NumberInt()
丹尼尔,你的解决方案不行……大卫的解决方案还可以
R
Russell
db.coll.find().forEach(function(data) {
    db.coll.update({_id:data._id},{$set:{myfield:parseInt(data.myfield)}});
})

u
user3616725

到目前为止,所有答案都使用某些版本的 forEach,在客户端迭代所有集合元素。

但是,您可以通过使用聚合管道和 $out stage 来使用 MongoDB 的服务器端处理:

$out 阶段用新的结果集合自动替换现有集合。

例子:

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

我不知道为什么这没有得到更多的支持。对大型数据集的逐行操作是对性能的谋杀
c
chridam

要将字符串类型的字段转换为日期字段,您需要在循环转换中使用 forEach() 方法迭代 find() 方法返回的光标该字段为 Date 对象,然后使用 $set 运算符更新该字段。

利用 Bulk API 进行批量更新,从而提供更好的性能,因为您将以 1000 次为单位向服务器发送操作,这样您就不会发送每个请求,从而获得更好的性能到服务器,每 1000 个请求中只有一次。

下面演示了这种方法,第一个示例使用 MongoDB 版本 >= 2.6 and < 3.2 中提供的 Bulk API。它通过将所有 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(); }

下一个示例适用于自 deprecated the Bulk API 以来的新 MongoDB 版本 3.2,并使用 bulkWrite() 提供了一组更新的 api:

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 });

很好的答案,bulk 方法对我来说运行速度快了大约 100 倍,尽管它看起来仍然是一个同步调用。
G
Giulio Roggero

要在 mongo 中将 int32 转换为字符串而不创建数组,只需将“”添加到您的号码:-)

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

F
Felipe

真正帮助我在 MondoDB 中更改对象类型的只是这行简单的代码,可能之前在这里提到过......:

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

用户是我的集合,年龄是具有字符串而不是整数(int32)的对象。


A
Amarendra Kumar
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);
});

A
Aakash

我需要更改集合中多个字段的数据类型,因此我使用以下内容在文档集合中进行了多个数据类型更改。回答一个老问题,但可能对其他人有帮助。

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); 
});

P
Pang

演示使用 mongoose 将字段 mid 的类型从字符串更改为 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 只是此类样式的另一个示例

数字、字符串、布尔值,希望答案对其他人有所帮助。


u
user3469031

我在 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)
    );


}