猫鼬模式中的“转换”如何工作?

Ibr*_*bra 5 javascript mongoose mongodb node.js

我的用户模型图片:在此输入图像描述 在我的用户模型中,我将此作为我的用户模型的第二个参数,删除__v并替换_idid

  {
    toJSON: {
      transform: function (doc, ret) {
        ret.id = ret._id;
        delete ret._id;
        delete ret.password;
        delete ret.__v;
      },
    },
  }
Run Code Online (Sandbox Code Playgroud)

在我的登录路由器中,我有这样的内容:

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

我从我的 console.log 得到这个

 {
  _id: 5fe81e29fdd22a00546b05e3,
  email: 'chs@hotmail.fr',
  password: '0636b425ef0add0056ec85a5596eacf9ff0c71f8c2a1d4bad068a8679398e11870df12262722b911502eacb5fca23cef0cdd3b740481102ead50c58756d14a34.3f82d856ad93bc99',
  __v: 0
}
Run Code Online (Sandbox Code Playgroud)

但在邮递员中我收到了这个:

{
    "email": "chs@hotmail.fr",
    "id": "5fe81e29fdd22a00546b05e3"
}
Run Code Online (Sandbox Code Playgroud)

我知道通过转换,“如果设置了,猫鼬将调用此函数以允许您转换返回的对象”。
但是有人可以向我解释一下何时发生“转换”以证明 console.log 和我在 postman 中收到的数据之间的差异是合理的吗?
这与异步有关系吗?

ank*_*zet 10

res.status(200).send(existingUser);看起来像expressjs(或看起来相似)控制器代码,所以我假设它是 Express。

.send(body)方法将响应作为字符串发送到客户端浏览器(技术上)。因此,在实际传输之前,如果参数还不是字符串,body则将其转换为字符串。在您的代码中不是字符串,它是猫鼬对象,因此将其转换为字符串,实际上这将类似于以下代码:stringexistingUserexpress

res.status(200)
  .send(
    existingUser.toString() // .toString() here is the key
  );
Run Code Online (Sandbox Code Playgroud)

在底层,mongoose对象.toString()被代理为.toJSON()方法,因此您的代码等效于以下内容:

  ...
  .send(
    existingUser.toJSON() // .toJSON() here
  );
Run Code Online (Sandbox Code Playgroud)

....toJSON()方法是考虑transform(doc, ret)您为猫鼬模式指定的选项的方法。

console.log()另一方面,不使用参数的底层.toString()/方法。.toJSON()如果您想打印以控制台结果,该结果将由最终消费者(邮递员,fe)接收,那么您应该手动调用转换:

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)
Run Code Online (Sandbox Code Playgroud)

整个变换链如下所示:

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 
Run Code Online (Sandbox Code Playgroud)