如何在Mongoose的findOneAndUpdate过滤器中正确使用_id?
解决Mongoose findOneAndUpdate中使用_id查询的问题
嘿,我完全懂你遇到的这个坑——Mongoose对_id的处理确实容易让人绕晕,让我一步步帮你理清:
首先纠正一个关键误解:你根本不需要手动在Schema里定义_id!
MongoDB和Mongoose默认会自动为每个文档生成一个ObjectId类型的_id字段,所以你的原始orderSchema完全没问题,千万别加_id: String这种定义——这会直接覆盖Mongoose的自动生成逻辑,导致你遇到“保存前文档必须有_id”的错误,因为手动定义后Mongoose就不会再帮你自动生成_id了。
为什么你的findOneAndUpdate查不到文档?
问题大概率出在idExample的类型上!MongoDB里的_id是ObjectId类型,如果你直接传入一个字符串格式的ID(比如从前端传来的字符串参数),Mongoose有时候不会自动转换类型,导致查询条件和数据库里的_id不匹配,自然查不到文档。
正确的解决步骤:
保持你的原始Schema不变:
var orderSchema = new mongoose.Schema({ deleted: Boolean, client: { name: String, phone: String }, products: [{ name: String, quantity: Number, price: Number }], seller_id: Number, order_id: Number, total: Number });这个Schema会自动拥有
ObjectId类型的_id字段,MongoDB会在保存文档时自动生成它。查询时把字符串ID转换为ObjectId:
使用mongoose.Types.ObjectId()将你的idExample转换成正确的类型,再传入查询条件:const mongoose = require('mongoose'); // 确保idExample是有效的24位十六进制字符串(比如"60d21b4667d0d8992e610c85") const targetId = mongoose.Types.ObjectId(idExample); let r = await Order.findOneAndUpdate( { _id: targetId, seller_id: json.seller_id }, order, { new: true } // 可选配置:返回更新后的文档,默认返回更新前的旧文档 );额外验证小技巧:
- 可以先执行
Order.findById(targetId)确认这个ID对应的文档确实存在于数据库中。 - 如果
idExample来自前端,要确保它是完整的24位十六进制字符串,格式错误的话转换会失败。
- 可以先执行
补充说明
如果你确实有特殊需求要自定义_id类型(比如用业务字符串代替ObjectId),那你必须在保存文档时手动给_id赋值,但这在绝大多数场景下都没必要——默认的ObjectId不仅能自动生成,MongoDB对它的索引效率也更高。
内容的提问来源于stack exchange,提问作者Poperton
相关产品推荐
相关产品推荐

