NodeJS中使用MongoDB的updateOne新增对象类型字段报错如何解决
问题原因及解决方案
核心原因
你遇到的问题是写入非空address对象时触发MongoDB的规则校验失败,具体诱因通常是以下两种情况:
- 你的
shops集合已针对address字段创建了2dsphere/2d地理空间索引,你传入的测试坐标[123, 321]不符合GeoJSON Point类型的格式要求:纬度的合法范围是-90~90,你的测试值321远超出合法区间,触发索引校验报错。 - 你的
shops集合配置了JSON Schema校验规则,限制了address字段的结构要求,空对象符合兜底校验规则所以可以写入,你传入的非空对象结构不符合规则被拦截。
解决步骤
- 校验坐标合法性并测试
先把测试坐标替换为合法的经纬度值,经度范围-180180,纬度范围-9090,示例:
替换后如果更新成功,即可确认是非法坐标导致的报错。$set: { address: { type: 'Point', coordinates: [116.403874, 39.914885] } } - 检查集合索引配置
在MongoDB shell中执行命令查看当前集合的索引,确认是否存在address字段的地理空间索引:
如果你不需要地理空间查询能力,可以删除对应索引,即可写入任意结构的address对象。db.shops.getIndexes() - 检查集合校验规则
执行以下命令查看集合的校验规则,确认address字段的结构要求:
根据返回的校验规则调整你写入的address对象结构即可。db.shops.getValidator() - 驱动API兼容排查(可选)
如果你使用的是4.x及以上版本的mongodb NodeJS驱动,ObjectID(D大写)已更名为ObjectId(d小写),建议修改引入和使用逻辑,避免类型异常:// 引入修改为小写d的ObjectId const { MongoClient, ObjectId } = require('mongodb'); // 调用时也用小写d的方法 { _id: ObjectId(_id) }
代码优化建议
不要把client.connect()写在每次调用的insertData方法内,会重复创建数据库连接,建议全局初始化一次MongoDB连接,业务逻辑中复用连接即可,避免连接泄露和性能损耗。
内容的提问来源于stack exchange,提问作者Alex Choi
相关产品推荐
相关产品推荐

