3

マングースに問題があります。私の目標は、事前保存中にオブジェクトを変更して、必要に応じてタグを分割したり、別のケースではサブドキュメントの長さの合計を計算してメインドキュメント内で更新したりできるようにすることです。

私が見つけたのは、モデルをロードしてから doc.update を呼び出して新しいデータを渡し、トリガーのみを呼び出し、ミドルウェア内のschema.pre('update', ...)変更が更新されないことです。また、更新ミドルウェア内でthis使用しようとしましたが、役に立ちませんでした。this.set('...', ....);

doc.save(...)代わりにそうすると、this内部への変更schema.pre('save', ...)が期待どおりに追加されるようです。投稿された変数をモデルのプロパティに拡張して保存する以外に、この目的で doc.update を活用する方法は見当たりません。

私の目標: - 既存のドキュメントを更新するdoc.update(properties, ....) - 保存中にミドルウェアを使用して、ドキュメントを変更し、高度な検証を行い、関連ドキュメントを更新する - 更新中にミドルウェアを使用して、ドキュメントを変更し、高度な検証を行い、関連ドキュメントを更新する - モデルを交換可能に使用する. findByIdAndUpdate、model.save、model.findById->doc.update、model.findById->doc.save、およびすべてが私の保存/更新ミドルウェアを利用しています。

いくつかの任意のサンプル コード:

function loadLocation(c) {
    var self = this;
    c.Location.findById(c.params.id, function(err, location) {
        c.respondTo(function(format) {
            if (err | !location) {
                format.json(function() {
                    c.send(err ? {
                        code: 500,
                        error: err
                    } : {
                        code: 404,
                        error: 'Location Not Found!'
                    });
                });
                format.html(function() {
                    c.redirect(c.path_to.admin_locations);
                });
            } else {
                self.location = location;
                c.next();
            }
        });
    });
}

LocationController.prototype.update = function update(c) {
    var location = this.location;
    this.title = 'Edit Location Details';

    location.update(c.body.Location, function(err) {
        c.respondTo(function(format) {
            format.json(function() {
                c.send(err ? {
                    code: 500,
                    error: location && location.errors || err
                } : {
                    code: 200,
                    location: location.toObject()
                });
            });
            format.html(function() {
                if (err) {
                    c.flash('error', JSON.stringify(err));
                } else {
                    c.flash('info', 'Location updated');
                }
                c.redirect(c.path_to.admin_location(location.id));
            });
        });
    });
};

module.exports = function(compound) {
    var schema = mongoose.Schema({
        name: String,
        address: String,
        tags: [{ type: String, index: true }],
        geo: {
            type: {
                type: String,
            default:
                "Point"
            },
            coordinates: [Number] // Longitude, Latitude
        }
    });
    schema.index({
        geo: '2dsphere'
    });
    var Location = mongoose.model('Location', schema);
    Location.modelName = 'Location';
    compound.models.Location = Location;

    schema.pre('save', function(next) {
        if(typeof this.tags === 'string') {
            this.tags = this.tags.split(',');
        }
    });
};

==== * 改訂サンプル * ====

module.exports = function(compound) {
    var schema = mongoose.Schema({
        name: String,
        bio: String
    });

    schema.pre('save', function(next) {
        console.log('Saving...');
        this.bio = "Tristique sed magna tortor?"; 
        next();
    });

    schema.pre('update', function(next) {
        console.log('Updating...');
        this.bio = "Quis ac, aenean egestas?"; 
        next();
    });

    var Author = mongoose.model('Author', schema);
    Author.modelName = 'Author';
    compound.models.Location = Author;
};
4

2 に答える 2

0

Mongoose は、Model Update API へのフックをサポートしていません。ただし、Monkey-patch を介して更新フックを実行できます。Hooker NPM パッケージは、これをきれいに行うための優れた方法です。

Node REST API のボイラープレートであるRESTeasyプロジェクトには、その方法を示すコードがあります。

var hooker = require('hooker');

var BaseSchema = new mongoose.Schema({
  sampleString: {
    type: String
  }
});

var BaseModel = mongoose.model('Base', BaseSchema);

// Utilize hooks for update operations. We do it in this way because MongooseJS
// does not natively support update hooks at the Schema level. This is a way
// to support it.
hooker.hook (BaseModel, 'update', {
  pre: function () {
    // Insert any logic you want before updating to occur here
    console.log('BaseModel pre update');
  },
  post: function () {
    // Insert any logic you want after updating to occur here
    console.log('BaseModel post update');
  }
});

// Export the Mongoose model
module.exports = BaseModel;
于 2014-09-22T23:11:59.310 に答える