David Tamrazov
David Tamrazov

Reputation: 597

Mongoose findOneAndUpdate not returning raw Mongo response

I'm trying to determine whether the document was found in my findOneAndUpdate operation. If it wasn't, I return a 404 not found error. I figured I'd use the "passRawValue" option Mongoose provides, and check for a raw value- if raw is undefined, I know the doc was not found.

However regardless whether the doc is found or not, my raw value is undefined. I've verified that the doc I'm trying to update is in the DB at the time of the query by running a simple "findOne" query just before the update. Where am I going wrong?

let updateItemById = (userId, itemId, params, cb) => {

//this finds and prints the document I'm testing with -- I know its in the DB

  // Item.findOne({ "_id" : itemId, ownerId: userId }, (err, doc) => {
  //   if (doc) {
  //     console.log("This is the doc: ", doc);
  //   }
  // });

  Item.findOneAndUpdate({ "_id" : itemId, ownerId: userId },
    {
      $set: {
        params
      }
    }, { runValidators: 1, passRawResult: true}, (err, doc, raw) => {

    if (err) {
      //winston.log
      return cb(ErrorTypes.serverError(), false);
    }
    else if (raw) {
      return cb(null, true);
    }
    else {
      return cb(ErrorTypes.notFound(), false);
    }

  });
} 

Upvotes: 0

Views: 2233

Answers (2)

Thélio Freitas
Thélio Freitas

Reputation: 3

I know it's been awhile but I had the same problem here so I decided to leave an answer that maybe can help other people.

I was able to check whether the findOneAndUpdate() method found a document or not by checking if the doc parameter was null on the callback function:

async Update(request: Request, response: Response) {
  const productId = request.params.id;

  const query = { _id: productId };
  const options = { new: true };

  try {
    await Product.findOneAndUpdate(query, request.body, options, (err, doc, res) => {
      if (doc === null)
        return response.status(404).send({
          error: 'Product not found'
        })
      return response.status(204).send();
    });
  }
  catch (err) {
    return response.status(400).send({
      error: 'Product update failed'
    });
  }
}

Upvotes: 0

Samip Suwal
Samip Suwal

Reputation: 1243

Hi I have a hunch that you are passing params that has a property that doesn't exist in the document in the database. In such case, nothing was modified, hence db doesn't return raw as the third parameter.

Update:

So I did some few tests of my own, and I see that if we pass option strict:false then your code should work as intended. So your options section will look like this

    { runValidators: 1, passRawResult: true, strict: false, new:true}

Explanation:

Mongoose has a strict option which by default is true. It makes sure that the values being updated is defined in the schema. So when we provide the option strict as false, as described in the [mongoose documentation] (http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate) we can achieve updating document with new field.

I also added new:true option which will return you the updated document.

P.S.

I would like to add though, since our upsert is false, which means it won't insert new document when a match is not found, it will return null for doc, and you can simple check on that. Why are you checking on raw? Is there any particular reason for this?

Upvotes: 2

Related Questions