为何MongoDB的JSON Schema验证允许NaN作为数字通过?
问题解析与解决方案
核心原因
MongoDB的BSON规范中,number类型包含了常规数字、NaN、Infinity、-Infinity这些特殊数值。所以当你的JSON Schema仅限制bsonType为"number"时,NaN会被判定为符合规则的值,从而通过验证。
解决办法
可以从「数据库Schema强化验证」和「后端提前校验」两个层面解决:
1. 完善MongoDB的JSON Schema,拦截特殊数值
修改users集合的Schema,添加额外规则排除NaN、Infinity这类无效值,同时可结合手机号的格式范围做更严格的校验:
{ "bsonType": "object", "properties": { "phone": { "bsonType": "number", // 排除NaN、正负无穷这类无效值 "not": { "enum": [NaN, Infinity, -Infinity] }, // 假设手机号为11位整数,根据实际业务调整范围 "minimum": 10000000000, "maximum": 99999999999, "description": "手机号必须是11位有效整数" }, "name": { "bsonType": "string", "description": "用户名不能为空" } }, "required": ["name", "phone"] }
2. 在Node.js后端提前校验,避免生成NaN
在解析手机号后立即检查是否为有效整数,无效则直接返回错误,不进入数据库插入流程:
app.use("/user/add", (req, res) => { const { name } = req.body; const phone = parseInt(req.body.phone); // 校验手机号是否为有效整数 if (isNaN(phone) || !Number.isInteger(phone)) { return res.status(400).json({ error: "请输入有效的手机号" }); } UserCollection.insertOne({ name, phone }) .then(() => res.status(201).json({ message: "用户添加成功" })) .catch(err => res.status(500).json({ error: err.message })); });
补充说明
parseInt()在遇到无法解析为整数的字符串时会返回NaN,这是JavaScript的特性。如果需要更严格的手机号格式校验(比如支持带区号、连字符的情况),可以改用正则表达式先匹配字符串格式,再转为数字;或者直接存储字符串类型的手机号——很多场景下,手机号存字符串更合理,能避免前导零丢失等问题。
内容的提问来源于stack exchange,提问作者FishLegs
相关产品推荐
相关产品推荐

