読者です 読者をやめる 読者になる 読者になる

Mongooseのupdateでvalidateが実行されない

 タイトル通りです。Schema定義でvalidateを記述しても、saveではvalidateされるのにupdateだとvalidateされません。なのでupdateをオーバーライトしてvalidateが実行されるようにしました。と言っても、findしてsaveしただけなんですが。saveはちゃんとvalidateされますからね。今のところ対応しているのは$setと$pushだけです。使い方としてはConnectionとModelを作って、それを引数としてsetNewUpdateを呼ぶとupdateが上書きされます。ConnectionはともかうModelを渡すの面倒なので、もっと一般化させたいですね。現状、upsertとmultiオプションには対応してないので、今後必要があれば対応するかもしれません。Gistに置いておきます。
https://gist.github.com/1385787

var update = require('update');
var con = mongoose.createConnection('mongodb:localhost/db');
var Account = con.Model('Account');
con = update.setNewUpdate(con, Account);
Account.update({id: 1}, {name: 'momota'}, {}, function(err) {});
module.exports = {
    'setNewUpdate': function(con, model) {
        con.base.Model.update = function(conditions, update, options, callback) {
            model.findOne(conditions, function(err, doc) {
                if (err) {
                    return callback(err);
                }
                if (!doc) {
                    return callback(new Error('Not exists.'));
                }
                for (var ope in update) {
                    switch (ope) {
                        case '$set':
                            for (var key in update['$set']) {
                                doc[key] = update['$set'][key];
                            }
                            // in save() validation run
                            doc.save(function(err) {
                                callback(err);
                            });
                            break;
                        case '$push':
                            for (var key in update['$push']) {
                                doc[key].push(update['$push'][key]);
                            }
                            // in save() validation run
                            doc.save(function(err) {
                                callback(err);
                            });
                            break;
                    }
                }
            });
        };
        return con;
    }
};