如何在Mongoose与Express.js中获取单一数值型deviceId?
将Mongoose中SchemaTypes.Long类型的deviceId转为单一数值返回
问题场景
使用Mongoose搭配Express.js存储车辆记录时,将deviceId字段定义为SchemaTypes.Long以适配大数值,但保存记录后API返回的deviceId是包含low、high、unsigned属性的对象,需要转为单一数值(或字符串)形式返回。
用户代码示例:
const mongoose = require("mongoose"); require('mongoose-long')(mongoose); var SchemaTypes = mongoose.Schema.Types; const carSchema = new mongoose.Schema({ name: { type: String, required: true }, deviceId: { type: SchemaTypes.Long, required: true, unique: true } }, { versionKey: false, virtuals: true }); module.exports = mongoose.model("car", carSchema); exports.carDemo = catchAsync(async (req, res, next) => { const car = await Car.create(req.body); res.status(statusCode.OK).json( car ); });
期望的响应格式:
{ "name": "I20", "deviceId":997786565423234, "_id":"66cf265cdcd77799f701efef" }
解决方案
方法1:在Schema中全局配置JSON转换规则
修改Schema的toJSON配置,添加转换函数自动处理Long类型字段:
const carSchema = new mongoose.Schema({ name: { type: String, required: true }, deviceId: { type: SchemaTypes.Long, required: true, unique: true } }, { versionKey: false, virtuals: true, toJSON: { transform: function(doc, ret) { // 转为数值(注意:若数值超过2^53-1,JS Number会丢失精度,建议转字符串) ret.deviceId = ret.deviceId.toNumber(); // 若需避免精度丢失,改用字符串:ret.deviceId = ret.deviceId.toString(); return ret; } } });
方法2:在响应时手动转换字段
在返回响应前,手动处理查询结果的deviceId:
exports.carDemo = catchAsync(async (req, res, next) => { const car = await Car.create(req.body); // 将Mongoose文档转为普通对象 const formattedCar = car.toObject(); // 转换deviceId为数值或字符串 formattedCar.deviceId = formattedCar.deviceId.toNumber(); res.status(statusCode.OK).json(formattedCar); });
方法3:使用虚拟字段(可选)
如果需要保留原始Long类型,同时提供格式化后的字段,可以定义虚拟字段:
// 在Schema中添加虚拟字段 carSchema.virtual('formattedDeviceId').get(function() { return this.deviceId.toNumber(); // 或toString() }); // 已有virtuals: true配置,虚拟字段会自动包含在JSON响应中
注意事项
若deviceId的数值超过JavaScript Number的安全范围(即大于2^53 - 1),使用toNumber()会导致精度丢失,此时建议转为字符串返回,确保数据准确性。
内容的提问来源于stack exchange,提问作者Spacewalker_vir
相关产品推荐
相关产品推荐

