db.items.aggregate([{ $group: {
_id: { $type: '$price' }, n: { $sum: 1 } } }]);
db.items.updateMany({ price: { $type: 'string' } },
[{ $set: { price: { $toDouble: '$price' } } }]);
价格范围查询的条数总比页面统计少,翻文档才发现部分文档的 price 存成了字符串。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,MongoDB 不做隐式类型转换,字符串和数字在索引里是两种值,范围查询只命中与条件同类型的文档,看起来就像丢数据。
「MongoDB 字段类型不一致」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。
验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
报错里带路径的,先去看那个路径在不在、权限对不对。
处理上按这个顺序:先按 $type 分组统计各类型的文档数量;用 updateMany 加管道把字符串转成数字;给这个字段加上校验规则,防止再写进字符串。
改完只确认一件事:同一查询的条数与页面统计一致,按类型分组只剩一种。
