Express.js路由使用_id字段查询MongoDB文档返回Null值(文档实际存在)
看起来你遇到的问题很典型,我帮你梳理几个最可能的原因和对应的解决办法:
先确认Express是否正确解析JSON请求体
你的日志里显示Request Body : [object Object],这说明直接把req.body对象转成字符串打印了,但更关键的是:如果Express没有配置JSON解析中间件,它根本无法正确解析axios发送的JSON请求体。你需要在Express应用的路由注册前添加express.json()中间件:const express = require('express'); const app = express(); // 必须在路由注册前添加这个中间件,否则无法解析JSON请求体 app.use(express.json()); // 再注册你的路由 app.use('/cancel_order', router);没有这个中间件的话,
req.body会是undefined或者空对象,即便日志里显示了Order IDs,也可能是临时调试的特殊情况,这个步骤一定要确认。检查_id的类型是否匹配
从Atlas触发器里拿到的purchase._id是MongoDB的ObjectId对象,通过axios发送时,JSON序列化会把它转成字符串形式的ObjectId(比如"651a92d88799f214af2e8a5d")。但如果你的PurchasesMongoose模型里错误地把_id定义成了String类型,而数据库里实际存储的是ObjectId,那用字符串查询就会找不到匹配的文档。
检查你的Purchases模型定义,确保_id是Mongoose默认的ObjectId类型(不需要手动定义,默认就会处理):const mongoose = require('mongoose'); const PurchaseSchema = new mongoose.Schema({ status: String, purchasedAt: Date, orderData: Array // 不需要手动指定_id类型,默认就是ObjectId }); const Purchases = mongoose.model('Purchases', PurchaseSchema);验证数据库和集合的匹配性
你的Atlas触发器连接的是test数据库的purchases集合,而你的Express应用连接的数据库是否也是test?虽然你说确认了实例正确,但数据库名可能不一致。检查你的Mongoose连接字符串,确保路径部分是/test:mongoose.connect('mongodb+srv://<user>:<password>@cluster0.mongodb.net/test?retryWrites=true&w=majority');Mongoose默认会把模型名转成小写复数作为集合名,
Purchases模型对应purchases集合,这部分和触发器里的集合名一致,不过还是可以再确认一下。调试时打印更详细的信息
把日志改成用JSON.stringify打印,这样能看到req.body的真实结构,以及orderID的类型:console.log(`Request Body :\n${JSON.stringify(req.body, null, 2)}`); console.log(`Order IDs : \n${JSON.stringify(orderIDs, null, 2)}`); // 打印orderID的类型,确认是字符串还是其他类型 for (const orderID of orderIDs) { console.log(`Processing orderID: ${orderID}, type: ${typeof orderID}`); const order = await Purchases.findById(orderID); console.log(`Found order: ${JSON.stringify(order, null, 2)}`); // ...后续代码 }这样能帮你确认
orderID的类型是否正确,以及req.body是否被正确解析。直接在数据库中测试查询
复制日志里的orderID,直接在MongoDB Atlas的查询界面执行:db.purchases.find({_id: ObjectId("651a92d88799f214af2e8a5d")})如果能查到文档,说明问题出在代码里的类型或解析环节;如果查不到,那可能是你找错了集合或数据库。
备注:内容来源于stack exchange,提问作者YKM

