代码之家  ›  专栏  ›  技术社区  ›  João Otero

事务内的mongoose findone():未捕获类型错误:无法读取未定义的属性“$elemmatch”

  •  0
  • João Otero  · 技术社区  · 6 年前

    我已经花了很多时间了,找不到解决办法。

    我正在使用node/express并尝试运行mongoose (^5.2.0) 芬达尼 与交易。对于数据库,我在内存中运行它, 运行rs .

    该集合以前是用有效文档填充的,我可以使用 蒙戈壳 :

    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)
    

    而且似乎在catch()中甚至没有捕捉到它,因为我的console.log从未被打印过。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Tomas Bruckner    6 年前

    尝试改变

    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)
    

    这两种方法都返回查询对象,该对象具有接受会话的方法会话(请参见 https://mongoosejs.com/docs/api.html#query_Query-session )

    我建议您先阅读有关交易的文档,以澄清其他事项: https://mongoosejs.com/docs/transactions.html

    编辑: 还使用 await 使用Mongoose时,需要使用 exec() 在查询结束时,因为查询对象不返回Promise,而只返回Table(请参见 https://mongoosejs.com/docs/promises.html )

    所以正确的查询应该如下所示

    const lot = await Lots.findById(lotId).session(session).exec();
    

    希望它有帮助, 托马斯:)