MongoDB类型更新从NumberLong到String。
MongoDB类型更新从NumberLong到String。
我已经将CSV文件导入到了我的mongodb中。CSV文件的分隔符是按照mongodb需要的方式设置的,并且是通过以下MySQL数据库查询语句获取的:
\nSELECT * FROM csgo_users INTO OUTFILE \'b1.csv\' FIELDS TERMINATED BY \',\' ENCLOSED BY \'\"\' LINES TERMINATED BY \'\\n\';
\n我还尝试使用Sequel Pro的导出功能来获取CSV文件。\n
\n在我的csv文件中,有一个字段的长度为17个字符。在MySQL数据库中,这个字段的类型是VARCHAR,但实际上它包含的是一个17位数的数字。
\n将csv文件导入到mongodb后,我发现这个字段的类型是NumberLong
,但我希望它是string
类型。
\n到目前为止,我尝试过以下方法:\n
- \n
- 将MySQL中的类型从
varchar
更改为text
。 - 尝试使用额外的标志
--headerline
和--columnsHaveTypes
导入csv文件 - 还尝试过添加不带顶行的单独字段,使用标记
--fields
。 - 尝试以下命令:
\ndb.csgo_users.find({"steam_id": {$type: 18}}) .toArray() .map(function(v){ v.steam_id = new String(v); db.csgo_users.save(v) })
\n
\n
\n
\n
\n或者这样:
\n
db.csgo_users.find({"steam_id": {$type: 18}}) .toArray() .map(function(v){ v.steam_id = new String(v.toSring()); db.csgo_users.save(v) })
\n
\n - 我尝试了很多使用forEach()
的解决方案,比如这个、这个或这个等等。\n
\n在最后一个尝试的例子中,我得到的不是字符串,而是一个对象,{\"N\",u\",\"m\",\"b\",\"e\",\"r\",\"L\",\"o\",\"n\",\"g\"..}
,但我希望它是\"123456789\",而不是对象。
\n我正在使用MongoDB 3.4的文档。
\n所以,我的问题是,如何将\"field\"的类型从NumberLong
更改为String
?
MongoDB中的数据类型从NumberLong转换为String的问题是由于JavaScript在处理大整数时的限制导致的。JavaScript中的整数最多只能表示53位,而ES6中最大的精确整数值是2^53-1,即9007199254740991。因此,将NumberLong转换为简单的字符串并不像之前的回答那样简单。下面是一个示例:
var huge = NumberLong("987654321987654321"); huge.valueOf(); // 987654321987654300 huge.toString(); // NumberLong("987654321987654321") huge.valueOf().toString(); // 987654321987654300
从上面的示例中可以看出,JavaScript在使用`valueOf()`时会对数字进行四舍五入,并且缺乏合理的响应和文档支持。为了解决这个问题,我使用了正则表达式来从`toString()`函数中移除非数字字符:
huge.toString().replace(/[^\d]/g, '') // 987654321987654321
这种方法虽然不够优雅,但是可以正常工作。如果有其他更好的解决方案,我会非常感激。值得一提的是,使用`JSON.stringify`将值转换为对象时,MongoDB会使用特殊字符`$`来表示在处理值时要调用的函数。这是MongoDB处理常见JSON对象时的方式:
JSON.stringify(huge) // {"$numberLong":"987654321987654321"}
更新:
在MongoDB中正确转换数据的方法是使用聚合操作的投影(projection):
db.getCollection('mycollection').aggregate([ {$match: { /* 匹配查询条件 */ }}, {$project: { _id: 0, // 忽略文档的id myStringObj: {$toString: '$myNumberLongObj'} // 从NumberLong转换为String }}, ], {allowDiskUse: true});
在正则表达式中,`\D`是`\d`的相反,所以可以稍微简短一些地写为`huge.toString().replace(/\D/g,"")`。
MongoDB中的NumberLong类型可以通过使用valueOf()方法将其转换为JavaScript的数字值。然后,可以使用toString()方法将该数字转换为字符串值。下面是一个示例:
NumberLong('5').valueOf() // 返回数字值 5 NumberLong('5').valueOf().toString() // 返回字符串值 "5"
如果想要在Mongo Shell查询中使用.valueOf(),可以使用$type运算符选择所有类型为NumberLong($type: 18)的字段,并将其替换为相同的值,但使用.toString()方法。以下是一个示例:
db.collection.find({ field: { $type: 18 } }).forEach(function(doc) { doc.field = doc.field.valueOf().toString(); db.collection.save(doc); });
如果要转换的数字很大,转换后可能会导致精度丢失。