Как работает `transform` в схеме mongoose?

#javascript #node.js #mongodb #mongoose

#javascript #node.js #mongodb #mongoose

Вопрос:

Изображение моей пользовательской модели:введите описание изображения здесь в моей пользовательской модели у меня есть это в качестве второго аргумента для моей пользовательской модели, для удаления __v и замены _id на id :

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

В моем маршрутизаторе входа у меня есть что-то вроде этого :

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

Я получил это из своего console.log

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

Но в postman я получил это :

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

Я знаю, что с помощью transform «если установлено, mongoose вызовет эту функцию, чтобы вы могли преобразовать возвращаемый объект».
Но не мог бы кто-нибудь объяснить мне, когда происходит ‘transform’, чтобы оправдать разницу между консолью.журнал и данные, которые я получил в postman?
Имеет ли это какое-то отношение к асинхронности?

Комментарии:

1. я не понял вашу проблему, вы хотите заменить id на _id и удалить __v ?

2. Все работает нормально. Чего я не понимаю, так это почему разные выходные данные между console.log(existingUser) и res.status(200).send(existingUser); Одна и та же переменная, но выходные данные разные, как объяснено выше.

3. Вы уверены, что это происходит? Я не верю, что ваш сервер будет по-разному реагировать на postman и console.log; Скорее всего, ваша консоль. аргумент журнала и аргумент res.send будут разными

4. Кроме того, попробуйте использовать метод ToObject () со свойством transform, например userSchema.options.toObject.transform = function(doc, output, options) { delete output.__v; return output; } , это очень полезная функциональность. Подробнее читайте здесь

Ответ №1:

res.status(200).send(existingUser); выглядит как expressjs (или похожий) код контроллера, поэтому я предполагаю, что это Express.

.send(body) метод отправляет ответ в клиентский браузер в виде строки (ну, технически). Итак, перед фактической передачей body аргумент преобразуется в string , если он еще не является строкой. existingUser в вашем коде это не строка, это объект mongoose, поэтому express он преобразует его в строку, фактически это будет похоже на следующий код:

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

Под капотом mongoose объект .toString() проксируется в .toJSON() метод, поэтому ваш код становится эквивалентным следующему:

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

…и .toJSON() метод — это то, что учитывает transform(doc, ret) параметр, который вы указали для схемы mongoose.

console.log() с другой стороны, не использует базовые .toString() / .toJSON() методы аргументов. Если вы хотите распечатать для консоли результат, который будет получен конечным потребителем (например, почтальоном), тогда вам следует вызвать преобразование вручную:

 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)
 

Вся цепочка преобразований выглядит следующим образом:

 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