Удаление атрибута из объекта 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
все еще существуют. Что я делаю не так? Любая помощь будет принята с благодарностью.
Спасибо!
Ответы
Ответ 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));