MPiland
MPiland

Reputation: 57

Mongoose findOneAndUpdate is not updating database

I have a database that has a structure to this. I've updated the values clearly, but the idea remains. I'm trying to essentially find the refresh token and update it with a new token. Here is the database structure sample

{
  "_id": "xxxxxxxxxxxxxxxxx",
  "username": "[email protected]",
  "refreshTokens": [
    {
      "refreshToken": "token_example_1",
      "_id": "xxxxxxxxxxxxxxxxx"
    }
  ],
  "salt": "salted_stuff",
  "hash": "hashed_stuff",
  "__v": 1
}

Here is my schema structure

const session = new Schema({
  refreshToken: {
    type: String,
    default: '',
  },
});

const userSchema = new Schema({
  password: String,
  refreshTokens: [session],
});

userSchema.set('toJSON', {
  transform: function (doc, ret, options) {
    delete ret.refreshToken;
    return ret;
  },
});

Now, what I'm trying to do to update it is

User.findOneAndUpdate(
        { _id: userId, refreshTokens: { $elemMatch: { refreshToken: refreshToken } } },
        { $set: { 'refreshTokens.$.refreshToken': newRefreshToken } }
      );

newRefreshToken is built from another function and userId is a variable based off another function of retrieving that internally. Both of those are working as I've consoled logged them and can see they are correct.

When I check the database, the refreshToken doesn't change after running the query.

Am I doing something wrong here? The original user creation and everything works fine so I know the connection is there and it's not returning any errors. Even this update isn't returning errors. It's just not updating the data.

I have scoured multiple other questions and forums. I tried mongoplayground and it seemed to work, so not sure why it's not actually working.

I've also tried

User.updateOne(
        { _id: userId, refreshTokens: { $elemMatch: { refreshToken: refreshToken } } },
        { $set: { 'refreshTokens.$.refreshToken': newRefreshToken } }
      );

and

User.findOneAndUpdate(
        { _id: userId, 'refreshTokens.refreshToken': refreshToken } } },
        { $set: { 'refreshTokens.$.refreshToken': newRefreshToken } }
      );

No success so far. And if I try to do a

.then((user) => {user.save()})

I get an error saying that is not a function.

Upvotes: 1

Views: 340

Answers (2)

MPiland
MPiland

Reputation: 57

For anyone else that runs across this with the same issue...

I ended up having to set the .post as an async function and then use .await plus .exec() for the findOneAndUpdate function like below

router.post('/refreshToken', async (req, res, next) => {
...
        await User.findOneAndUpdate(
          {
            _id: userId,
            refreshTokens: {
              $elemMatch: { refreshToken: refreshToken },
            },
          },
          {
            $set: { 'refreshTokens.$.refreshToken': newRefreshToken },
          }
        )
          .exec()
...
}

This forced the database to update before creating the new cookie and storing the new token.

Upvotes: 1

Khoa Bui
Khoa Bui

Reputation: 11

I notice that you have 2 extra brackets in your original code. The fix is below:

{
    "_id": "64480569a2c60bc65d10b377",
    "username": "[email protected]",
    "refreshTokens": [
      {
        "refreshToken": "token_example_1",
        "_id": "64480569a2c60bc65d10b37a"
        }
    ],
    "salt": "salted_stuff",
    "hash": "hashed_stuff",
    "__v": 1
  }
  

Maybe instead of

User.findOneAndUpdate(
        { _id: userId, refreshTokens: { $elemMatch: { refreshToken: refreshToken } } },
        { $set: { 'refreshTokens.$.refreshToken': newRefreshToken } }
      );

You can try:

User.findOneAndUpdate(
        { _id: userId, "refreshTokens.refreshToken": refreshToken  },
        { $set: { 'refreshTokens.$.refreshToken': newRefreshToken } }
      );

Upvotes: 1

Related Questions