You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:30:50