JavaScript中MongoDB的Int32类型price无法转千分位字符串怎么办?
问题:MongoDB返回的Int32类型price字段无法转换为千分位字符串
问题场景
从MongoDB拉取hotAsset: true的Asset集合数据,price字段为Int32类型:
const hotAssets = await Asset.find({ hotAsset: true });
将数组传入工具函数试图把price转为带千分位的字符串,但修改始终不生效:
函数调用:
Utils.assetPriceToString(hotAssets);
函数实现:
exports.assetPriceToString = (assetsArray) => { for (const asset of assetsArray) { if (asset.price) asset.price = asset.price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); } };
集合数据示例:
{ location: { coordinates: [Array], title: 'Central Park Burgas', type: 'Point' }, _id: new ObjectId('66420dbd1ada8e8e709e30a7'), id: 3698, name: 'new flat', slug: 'new-flat', price: 120000, project: 'Central Park Burgas', city: 'Burgas', type: 'דירה', sm: '82 מ"ר', oceanView: '', rooms: '2', bathrooms: 1, terraces: '1', floor: '18 מ 20', readiness: '', serviceTax: '', description: 'some descriptin', year: 2008, mainImage: '/img/asset1.jpg', images: [ '/img/asset1.jpg', '/img/asset2.jpg', '/img/asset3.jpg', '/img/asset4.jpg', '/img/asset5.jpg', '/img/asset6.jpg', '/img/asset7.jpg', '/img/asset8.jpg', '/img/asset9.jpg', '/img/asset10.jpg', '/img/asset11.jpg', '/img/asset12.jpg', '/img/asset13.jpg', '/img/asset14.jpg', '/img/asset15.jpg', '/img/asset16.jpg', '/img/asset17.jpg', '/img/asset18.jpg', '/img/asset19.jpg', '/img/asset20.jpg', '/img/asset21.jpg', '/img/asset22.jpg', '/img/asset23.jpg' ], hotAsset: true, updated_at: 2024-05-13T12:55:24.545Z, __v: 0, priceNis: 482027 }
测试发现:硬编码的普通JS对象数组转换正常,但MongoDB返回的price字段,用toString()、String()、Intl.NumberFormat.format()等方法转换后,控制台打印看似是字符串,实际赋值后未生效。
原因分析
MongoDB驱动(Mongoose)返回的文档是不可变的Mongoose Document对象,而非普通JavaScript对象。Document对象内置了类型校验和属性拦截机制,会强制保持字段的原始数据类型(这里是Int32)。即使你赋值了字符串,它会自动转回Int32类型,导致修改无效。
解决方案
方案1:拉取数据时直接转为普通JS对象
在查询时添加.lean()方法,跳过Mongoose的Document包装,直接获取普通JS对象:
const hotAssets = await Asset.find({ hotAsset: true }).lean();
之后再调用Utils.assetPriceToString(hotAssets),就能正常修改price字段。
方案2:在工具函数内转换单个Document
如果不想全局使用.lean(),可以在函数内将每个Asset Document转为普通对象:
exports.assetPriceToString = (assetsArray) => { return assetsArray.map(asset => { // 转为普通JS对象 const plainAsset = asset.toObject(); if (plainAsset.price) { // 用正则或Intl.NumberFormat转换千分位 plainAsset.price = new Intl.NumberFormat().format(plainAsset.price); } return plainAsset; }); };
调用时接收返回的修改后数组:
const formattedHotAssets = Utils.assetPriceToString(hotAssets);
方案3:用Intl.NumberFormat替代正则(更优雅)
不管用哪种方式转换对象,都推荐用Intl.NumberFormat替代手动正则,它支持多语言环境,代码更简洁:
// 转换逻辑替换为: plainAsset.price = new Intl.NumberFormat().format(plainAsset.price);
比如输入120000会直接得到"120,000"。
内容的提问来源于stack exchange,提问作者Dror Salomon
相关产品推荐
相关产品推荐

