Подтвердить что ты не робот

Удаление атрибута из объекта JavaScript, возвращенного методом Mongoose "findOneAndUpdate"

Я пишу простой сервер в JavaScript на Node.js, который (среди прочего) позволяет пользователю управлять своей учетной записью (базовые функции CRUD и т.д.). Сервер подключается к экземпляру MongoDB, используя Mongoose для управления соединением и данными.

Модели в Mongoose имеют метод под названием findOneAndUpdate(), который делает именно то, что, по вашему мнению, он делает: запрашивает базу данных для первого возвращенного документа и обновляет указанный документ на основе параметров, которые вы передали. Затем он возвращает пользователю новый обновленный документ. Он работает точно так, как предполагалось, и у меня нет проблем с ним.

Однако я не хочу, чтобы ВСЕ данные пользователя возвращались. В частности, я хотел бы опустить поля _id и password. Поскольку объект, возвращенный MongoDB, является основным объектом JavaScript, я предположил, что смогу удалить эти атрибуты, вызвав delete object.attribute. К сожалению, по какой-то причине это не работает.

Здесь мой код, который обновляет информацию о пользователе:

case "update":
  User.findOneAndUpdate({"token": header.token}, body, function(err, user) {
    if (err) {
      return callback(err);
    } else {
      delete user["_id"];
      delete user["password"];
      return callback(null, new SuccessEnvelope(user));
    }
  });
  break;

Для ясности, Envelope (в данном случае a SuccessEnvelope) представляет собой пакет информации, который нужен клиенту и серверу для облегчения связи. Аналогично с TCP-пакетом. Во всяком случае, я отвлекаюсь...

Например, если я хочу обновить свое имя пользователя от "joe_bob" до "jim_bob", я бы отправил его на сервер:

{"header": "type": "user", "method": "update", "token": "IM_A_TOKEN_GAIS_SRSLY"}, "body": {"username": "jim_bob"}}

И пока пользовательское имя пользователя будет успешно обновлено, это то, что я получаю взамен:

{"header": {"type": "success"}, "body": {"__v": 0, "_id":"SOME_NUMERICAL_ID", "email": "[email protected]", "password": "SUPER_SECURE_PASSWORD_HASH_COME_AT_ME_NSA", "token": "IM_A_TOKEN_GAIS_SRSLY", "username": "jim_bob"}}

Как видите, _id и password все еще существуют. Что я делаю не так? Любая помощь будет принята с благодарностью.

Спасибо!

4b9b3361

Ответ 1

Установить select: false в схеме для свойств, которые обычно не нужны

mongodb позволяет запросам указывать, какие свойства должна возвращать база данных в объектах ответа. Mongoose поддерживает это несколькими вещами, в том числе явными списками полей, а также схемами, согласно которым каждое свойство может быть выбрано по умолчанию или нет. Поэтому для этого варианта использования лучше всего установить для вашего пароля поле по умолчанию:

var userSchema = new mongoose.Schema({
  passwordHash: {type: String, select: false}
  ...
});

Тогда вы знаете, что он никогда не вернется автоматически. Однако, когда вы действительно переходите на обработку запроса на вход, вам это нужно, и в этом случае вы явно запрашиваете его:

User.findOne({email: theEmail}, '+passwordHash', callback);

Для раздражающего свойства _id используйте преобразования схемы

Вещь _id вызывает много головных болей. Mongoose обращается к этому прямо в документации:

// specify the transform schema option
if (!schema.options.toObject) schema.options.toObject = {};
schema.options.toObject.transform = function (doc, ret, options) {
  // remove the _id of every document before returning the result
  delete ret._id;
}

Обратите внимание, что в комментариях OP сообщения успешно выполняют select: false для _id. Если это работает без проблем, это хорошее чистое решение. Я не пробовал, но я беспокоюсь, что это может сломать некоторые вещи.

Ответ 2

Параметр user, возвращаемый вызовом, является экземпляром Model, в данном случае user.

Если вы хотите использовать его как необработанный объект JavaScript, вам нужно будет его преобразовать с помощью toObject. Это возвращает простой JavaScript-объект JavaScript. При этом вы можете использовать delete и удалить все необходимые свойства.

user = user.toObject(); // swap for a plain javascript object instance
delete user["_id"];
delete user["password"];
return callback(null, new SuccessEnvelope(user));