简体   繁体   中英

How `transform` in mongoose schema works?

Picture of my user model: 在此处输入图像描述 In my user model I have this as second argument to my user model, to delete __v and replace _id by id :

  {
    toJSON: {
      transform: function (doc, ret) {
        ret.id = ret._id;
        delete ret._id;
        delete ret.password;
        delete ret.__v;
      },
    },
  }

In my signin router I have something like this:

const existingUser = await User.findOne({email});
console.log("existingUser*", existingUser)
res.status(200).send(existingUser);

I got this from my console.log

 {
  _id: 5fe81e29fdd22a00546b05e3,
  email: 'chs@hotmail.fr',
  password: '0636b425ef0add0056ec85a5596eacf9ff0c71f8c2a1d4bad068a8679398e11870df12262722b911502eacb5fca23cef0cdd3b740481102ead50c58756d14a34.3f82d856ad93bc99',
  __v: 0
}

But in postman I received this:

{
    "email": "chs@hotmail.fr",
    "id": "5fe81e29fdd22a00546b05e3"
}

I know that with transform, "if set, mongoose will call this function to allow you to transform the returned object".
But could someone explain to me when the 'transform' occurs to justify the difference between the console.log and the data I received in postman?
Does this have something to do with asynchronous?

res.status(200).send(existingUser); looks like expressjs (or look-alike) controller code, so i'll assume it is Express.

.send(body) method sends response to the client browser as a string (well, technically). So, before actual transmission, the body argument is converted to string if it isn't a string already. existingUser in your code isn't a string, it's a mongoose object, so express casts it to a string, effectively this will be similar to the following code:

res.status(200)
  .send(
    existingUser.toString() // .toString() here is the key
  );

Under the hood, mongoose object's .toString() is proxied to .toJSON() method, so your code becomes equivalent to following:

  ...
  .send(
    existingUser.toJSON() // .toJSON() here
  );

...and .toJSON() method is what takes into account the transform(doc, ret) option, that you specified for the mongoose schema.

console.log() on the other hand, does not use underlying .toString() / .toJSON() methods of the arguments. If you want to print to console the result, that would be received by the end consumer (postman, fe), then you should call the transform manually:

console.log(existingUser.toJSON()); // like this, transformed, but not stringified
console.log(existingUser.toString()); // or like this, but already stringified
console.log(JSON.stringify(existingUser, null, 3)); // or transform and then stringify with custom formatting (3-space tabulated instead of default single-line formatting)

The whole transform chain looks like this:

Model
  -> `.toJSON()` 
    -> Mongoose transforms model internally into POJO
      if custom transform is defined
      -> Mongoose passes POJO to user defined `transform(doc, ret)`, 
         where `doc` - original document, `ret` - internally transformed POJO
        -> `ret` is returned
      else
      -> POJO is returned 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM