2013-09-13 2 views
19

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

Модели в 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 (в данном случае, 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 все еще там. Что я делаю не так? Любая помощь будет принята с благодарностью.

Спасибо!

ответ

46

Set выберите: ложь в схеме для свойств, как правило, не хотели

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

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

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

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

Для раздражающих _ID собственности, использование схемы превращает

_id вещь вызывает много люди головные боли.Mongoose адрес это непосредственно в documentation:

// 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. Если это работает без проблем, это хорошее чистое решение. Я не пробовал, но я беспокоюсь, что это может сломать некоторые вещи.

+0

Это замечательно! Спасибо за ваш ответ! –

+1

Кроме того, чтобы добавить к этому, я закончил явно создание атрибута «_id» в схеме и изменил свойство «select» на false, как и то, что вы сделали с вашим атрибутом passwordHash. –

+3

Чтобы добавить назад несколько, отделите их во втором параметре с пробелами: '' + prop1 + prop2'' –

53

Параметр 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)); 
+2

+1 Я не знал, что 'toObject()' существовал, мы использовали 'JSON.parse (JSON.stringify (obj));' перед тем, как найти это. –

+1

О человек. Преобразование моего объекта (?) В объект делало трюк. Irreal, но он работает! Я мог бы потратить неделю на это. Большое вам спасибо :) –

+0

Он работает! просто упоминает, что это нужно делать в каждом результате, например: 'obj = results [i] .toObject();' где 'i' - индекс цикла. – Mikel

Смежные вопросы