MongoDB 将字符串类型转换为浮点类型
MongoDB convert string type to float type
按照此处的建议MongoDB: How to change the type of a field?我尝试更新我的集合以更改字段类型及其值。
这是更新查询
db.MyCollection.find({"ProjectID" : 44, "Cost": {$exists: true}}).forEach(function(doc){
if(doc.Cost.length > 0){
var newCost = doc.Cost.replace(/,/g, '').replace(/$/g, '');
doc.Cost = parseFloat(newCost).toFixed(2);
db.MyCollection.save(doc);
} // End of If Condition
}) // End of foreach
完成上面的查询后,当我运行下面的命令
db.MyCollection.find({"ProjectID" : 44},{Cost:1})
我还有 Cost
字段作为字符串。
{
"_id" : ObjectId("576919b66bab3bfcb9ff0915"),
"Cost" : "11531.23"
}
/* 7 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0916"),
"Cost" : "13900.64"
}
/* 8 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0917"),
"Cost" : "15000.86"
}
我做错了什么?
这是示例文档
/* 2 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0911"),
"Cost" : ",100.00"
}
/* 3 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0912"),
"Cost" : ",500.00"
}
/* 4 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0913"),
"Cost" : ",619.00"
}
/* 5 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0914"),
"Cost" : ",250.00"
}
问题是 toFixed
returns 一个 String
,而不是 Number
。然后你只是用一个新的、不同的 String
.
更新文档
示例来自 Mongo Shell:
> number = 2.3431
2.3431
> number.toFixed(2)
2.34
> typeof number.toFixed(2)
string
如果你想要一个 2 位小数,你必须用类似的东西再次解析它:
db.MyCollection.find({"ProjectID" : 44, "Cost": {$exists: true}}).forEach(function(doc){
if(doc.Cost.length > 0){
var newCost = doc.Cost.replace(/,/g, '').replace(/$/g, '');
var costString = parseFloat(newCost).toFixed(2);
doc.Cost = parseFloat(costString);
db.MyCollection.save(doc);
} // End of If Condition
}) // End of foreach
按照此模式将字符串类型的货币字段转换为浮点数。您需要查询集合中所有具有 Cost 字段类型字符串的文档。为此,您需要利用 Bulk API
进行批量更新。这些提供了更好的性能,因为您将以 1000 次为单位向服务器发送操作,这为您提供了更好的性能,因为您不是将每个请求都发送到服务器,而是每 1000 个请求发送一次。
下面演示了这种方法,第一个示例使用 MongoDB 版本 >= 2.6 and < 3.2
中可用的批量 API。它更新所有
通过将所有 Cost
字段更改为浮动值字段,集合中的文档:
var bulk = db.MyCollection.initializeUnorderedBulkOp(),
counter = 0;
db.MyCollection.find({
"Cost": { "$exists": true, "$type": 2 }
}).forEach(function (doc) {
var newCost = Number(doc.Cost.replace(/[^0-9\.]+/g,""));
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "Cost": newCost }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations
// re-initialize every 1000 update statements
bulk = db.MyCollection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }
下一个示例适用于新的 MongoDB 版本 3.2,该版本自 弃用 Bulk API
和使用 bulkWrite()
.
提供了一组更新的 API
它使用与上面相同的游标,但使用相同的 forEach()
游标方法创建具有批量操作的数组,以将每个批量写入文档推送到数组。因为写入命令最多可以接受 1000 个操作,所以您需要将操作分组为最多 1000 个操作,并在循环达到 1000 次迭代时重新初始化数组:
var cursor = db.MyCollection.find({ "Cost": { "$exists": true, "$type": 2 } }),
bulkUpdateOps = [];
cursor.forEach(function(doc){
var newCost = Number(doc.Cost.replace(/[^0-9\.]+/g,""));
bulkUpdateOps.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "Cost": newCost } }
}
});
if (bulkUpdateOps.length == 1000) {
db.MyCollection.bulkWrite(bulkUpdateOps);
bulkUpdateOps = [];
}
});
if (bulkUpdateOps.length > 0) { db.MyCollection.bulkWrite(bulkUpdateOps); }
按照此处的建议MongoDB: How to change the type of a field?我尝试更新我的集合以更改字段类型及其值。
这是更新查询
db.MyCollection.find({"ProjectID" : 44, "Cost": {$exists: true}}).forEach(function(doc){
if(doc.Cost.length > 0){
var newCost = doc.Cost.replace(/,/g, '').replace(/$/g, '');
doc.Cost = parseFloat(newCost).toFixed(2);
db.MyCollection.save(doc);
} // End of If Condition
}) // End of foreach
完成上面的查询后,当我运行下面的命令
db.MyCollection.find({"ProjectID" : 44},{Cost:1})
我还有 Cost
字段作为字符串。
{
"_id" : ObjectId("576919b66bab3bfcb9ff0915"),
"Cost" : "11531.23"
}
/* 7 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0916"),
"Cost" : "13900.64"
}
/* 8 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0917"),
"Cost" : "15000.86"
}
我做错了什么?
这是示例文档
/* 2 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0911"),
"Cost" : ",100.00"
}
/* 3 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0912"),
"Cost" : ",500.00"
}
/* 4 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0913"),
"Cost" : ",619.00"
}
/* 5 */
{
"_id" : ObjectId("576919b66bab3bfcb9ff0914"),
"Cost" : ",250.00"
}
问题是 toFixed
returns 一个 String
,而不是 Number
。然后你只是用一个新的、不同的 String
.
示例来自 Mongo Shell:
> number = 2.3431
2.3431
> number.toFixed(2)
2.34
> typeof number.toFixed(2)
string
如果你想要一个 2 位小数,你必须用类似的东西再次解析它:
db.MyCollection.find({"ProjectID" : 44, "Cost": {$exists: true}}).forEach(function(doc){
if(doc.Cost.length > 0){
var newCost = doc.Cost.replace(/,/g, '').replace(/$/g, '');
var costString = parseFloat(newCost).toFixed(2);
doc.Cost = parseFloat(costString);
db.MyCollection.save(doc);
} // End of If Condition
}) // End of foreach
按照此模式将字符串类型的货币字段转换为浮点数。您需要查询集合中所有具有 Cost 字段类型字符串的文档。为此,您需要利用 Bulk API
进行批量更新。这些提供了更好的性能,因为您将以 1000 次为单位向服务器发送操作,这为您提供了更好的性能,因为您不是将每个请求都发送到服务器,而是每 1000 个请求发送一次。
下面演示了这种方法,第一个示例使用 MongoDB 版本 >= 2.6 and < 3.2
中可用的批量 API。它更新所有
通过将所有 Cost
字段更改为浮动值字段,集合中的文档:
var bulk = db.MyCollection.initializeUnorderedBulkOp(),
counter = 0;
db.MyCollection.find({
"Cost": { "$exists": true, "$type": 2 }
}).forEach(function (doc) {
var newCost = Number(doc.Cost.replace(/[^0-9\.]+/g,""));
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "Cost": newCost }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations
// re-initialize every 1000 update statements
bulk = db.MyCollection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }
下一个示例适用于新的 MongoDB 版本 3.2,该版本自 弃用 Bulk API
和使用 bulkWrite()
.
它使用与上面相同的游标,但使用相同的 forEach()
游标方法创建具有批量操作的数组,以将每个批量写入文档推送到数组。因为写入命令最多可以接受 1000 个操作,所以您需要将操作分组为最多 1000 个操作,并在循环达到 1000 次迭代时重新初始化数组:
var cursor = db.MyCollection.find({ "Cost": { "$exists": true, "$type": 2 } }),
bulkUpdateOps = [];
cursor.forEach(function(doc){
var newCost = Number(doc.Cost.replace(/[^0-9\.]+/g,""));
bulkUpdateOps.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "Cost": newCost } }
}
});
if (bulkUpdateOps.length == 1000) {
db.MyCollection.bulkWrite(bulkUpdateOps);
bulkUpdateOps = [];
}
});
if (bulkUpdateOps.length > 0) { db.MyCollection.bulkWrite(bulkUpdateOps); }