Mongoose findOne () внутри транзакции: Uncaught TypeError: Невозможно прочитать свойство '$ elemMatch' из неопределенного - PullRequest
0 голосов
/ 08 января 2019

У меня уже много часов на это, и я не могу найти решение.

Я использую 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)

И кажется, что он даже не пойман в catch (), так как мой console.log никогда не печатается.

1 Ответ

0 голосов
/ 08 января 2019

Попробуйте изменить

findOne(lotId, session)

до

findById(lotId).session(session)

Mongoose использует драйвер MongoDB Node.js, синтаксис которого несколько отличается от собственного MongoDB. Метод findOne принимает объект, а не идентификатор (см. https://mongoosejs.com/docs/api.html#model_Model.findOne)., поэтому вы можете использовать

findOne({ _id: lotId })

или просто

findById(lotId)

Оба эти метода возвращают объект Query, у которого есть метод session, который принимает сеанс (см. https://mongoosejs.com/docs/api.html#query_Query-session).

Я рекомендую вам сначала прочитать документацию о транзакциях, чтобы уточнить другие вопросы: https://mongoosejs.com/docs/transactions.html

редактировать: Также, чтобы использовать await с Mongoose, вам необходимо использовать exec() в конце запроса, потому что объект Query не возвращает Promise и возвращает только затем (см. https://mongoosejs.com/docs/promises.html).

Таким образом, правильный запрос должен выглядеть следующим образом

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

Надеюсь, это поможет, Томас:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...