williamkapke / mongo-mock

Let's pretend we have a real MongoDB
MIT License
240 stars 74 forks source link

findOneAndUpdate with $and #113

Closed mt-sebastien-robert closed 4 years ago

mt-sebastien-robert commented 4 years ago

I'm using mongo-mock version 3.8.1 and I run this query:

// sample values:
const who = 123;
const timestamp = 1;
const what = {
    one: 'one',
    two: two
};

await collection.findOneAndUpdate(
      { $and: [{ _id: who }, { ts: { $lt: timestamp } }] },
      { $set: what },
      { upsert: true }
);

This works perfectly with a real MongoDB 3.6, but fails with mongo-mock. I run this with Jest (unit test) and get the following:

ModifyJsError: Invalid modifier specified $and

      at ModifyJsError (../node_modules/modifyjs/dist/bundle.js:141:11)
      at ../node_modules/modifyjs/dist/bundle.js:186:27
      at ../node_modules/modifyjs/dist/bundle.js:68:5
          at Array.forEach (<anonymous>)
      at Object.each (../node_modules/modifyjs/dist/bundle.js:67:32)
      at _modify (../node_modules/modifyjs/dist/bundle.js:183:7)
      at modify (../node_modules/modifyjs/dist/bundle.js:163:10)
      at upsertClone (../node_modules/mongo-mock/lib/collection.js:526:57)
      at Timeout._onTimeout (../node_modules/mongo-mock/lib/collection.js:447:27)

The thing is, I cannot catch it. When I log before and after await, I see the log before but not the one after, so I assume the promise returned never resolves nor rejects.

If it can help you to investigate, we have found that on the following line, the second call to modifyjs (from left to right) should probably not be based on the selector. The selector contains $and, and modifyjs seems to not support this operator. https://github.com/williamkapke/mongo-mock/blob/master/lib/collection.js#L526

However, I've tried to quickly tweak the code of mongo-mock but couldn't fix the problem, so the above assumption may be wrong. Note sure.

Thank you for your consideration.