如何更改字段的类型?

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

我在做这个..

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

但它不起作用!

257180 次浏览

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

在本例中,看起来您正在尝试更改$type从1(双精度)到2(字符串)

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

如果您需要完全通过shell以编程方式执行此操作,则可以使用find(...).forEach(function(x) {})语法。


回应下面的第二条评论。在集合foo中,将字段bad从数字更改为字符串。

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

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

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

用于字符串到整型的转换。

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);
db.coll.find().forEach(function(data) {
db.coll.update({_id:data._id},{$set:{myfield:parseInt(data.myfield)}});
})

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




}

在Mongo中将Int32转换为String,而不创建数组__ABC__(0:-)

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

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

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

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

利用使用批量API进行批量更新的优势,这可以提供更好的性能,因为您将以批处理(比如1000个)的方式向服务器发送操作,这可以提供更好的性能,因为您不会将每个请求都发送到服务器,而是每1000个请求发送一次。

下面演示了这种方法,第一个示例使用MongoDB版本>= 2.6 and < 3.2中可用的批量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(); }

下一个示例应用于新的MongoDB版本3.2,该版本自__以来一直使用ABC__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 });
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);
});

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

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

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

演示使用Mongoose将字段类型从String更改为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只是此类样式的另一个示例,如

数字,字符串,布尔值,希望答案能帮助别人。

到目前为止,所有答案都使用某个版本的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',
},
]);

开始Mongo 4.2db.collection.update()可以接受聚合管道,最终允许基于其自身的值更新字段:

// { a: "45", b: "x" }
// { a:  53,  b: "y" }
db.collection.updateMany(
{ a : { $type: 1 } },
[{ $set: { a: { $toString: "$a" } } }]
)
// { 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中引入的新聚合运算符。

如果强制转换不是从double到string,则可以在Mongo 4.0中引入的不同转换运算符之间进行选择,例如$toBool$toInt,..。

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

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