我已经花了很多时间了,我找不到解决办法。
我正在使用Node / Express,并尝试运行带有交易的Mongoose (^5.2.0)
findOne 。对于数据库,我使用 run-rs 在内存中运行它。
该集合之前已填充有效文档,我可以使用 mongo shell 找到该文档:
rs:PRIMARY> db.lots.findOne("aaaabbbbccccdddd11112222")
{
"_id" : ObjectId("aaaabbbbccccdddd11112222"),
"availableQty" : 0,
"expirationDate" : ISODate("2019-01-10T15:10:29.455Z"),
"__v" : 0
}
但是,每当我在下面运行此代码时,都会出现错误:
const save = async (lotId) => {
const session = await mongoose.startSession()
await session.startTransaction()
try {
let lot = await Lots.findOne(lotId, session)
console.log('result: ' + lot)
await session.commitTransaction()
await session.endSession()
return lot
} catch(err) {
console.error('caught error: ' + err)
await session.abortTransaction()
await session.endSession()
throw err
}
}
错误:
Uncaught TypeError: Cannot read property '$elemMatch' of undefined
at model.Query._castFields (node_modules/mongoose/lib/query.js:3873:22)
at model.Query.Query._findOne (node_modules/mongoose/lib/query.js:1861:23)
at process.nextTick (node_modules/kareem/index.js:333:33)
at _combinedTickCallback (internal/process/next_tick.js:95:7)
at process._tickCallback (internal/process/next_tick.js:161:9)
由于我的console.log从未被打印过,因此似乎甚至没有被catch()捕获。
答案 0 :(得分:0)
尝试更改
findOne(lotId, session)
到
findById(lotId).session(session)
Mongoose使用Node.js MongoDB驱动程序,该驱动程序的语法与本机MongoDB略有不同。方法findOne接受不是id的对象(请参见https://mongoosejs.com/docs/api.html#model_Model.findOne)。所以您可以使用
findOne({ _id: lotId })
或者简单地
findById(lotId)
这两个方法都返回带有方法session的Query对象,该对象接受会话(请参见https://mongoosejs.com/docs/api.html#query_Query-session)。
我建议您先阅读有关交易的文档以阐明其他内容:https://mongoosejs.com/docs/transactions.html
编辑:
另外,要将await
与Mongoose一起使用,您还需要在查询结束时使用exec()
,因为Query对象不返回Promise而是仅返回thenable(请参阅https://mongoosejs.com/docs/promises.html)。
因此正确的查询应如下所示
const lot = await Lots.findById(lotId).session(session).exec();
希望有帮助, 托马斯:)