Предварительный документ Mongoose предварительно удалить промежуточное программное обеспечение не называется

Я бы запретил удаление любого дополнительного документа, поэтому я добавил ошибку в промежуточное программное обеспечение pre('remove') каждой схемы дополнительного документа.

При вызове функции.remove() она эффективно вызывает промежуточное программное обеспечение. Но когда он удаляется без вызова remove(), промежуточное ПО не проверяет, было ли оно удалено.

Случаи, когда дело обстоит так, когда я получаю объект из удаленного источника, я хотел бы выполнить все проверки целостности через промежуточное ПО mongoose, чтобы держать все в одном месте. Удаленный источник может по ошибке или нет удалить один из вложенных документов. Поэтому, когда Mongoose проверяет весь документ, вспомогательный документ уже удален без вызова функции.remove().

Вот минимальный рабочий пример моей проблемы:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var subDateSchema = new Schema({
    date_add: {type: Date, default: Date.now},
    date_remove: {type: Date, default: null}
});

var ResourceSchema = new Schema({
    activation_dates: [subDateSchema]
});

subDateSchema.pre('remove', function(next){
    next(new Error("YOU CAN'T DELETE ANY ACTIVATION DATE"));
});

var Resource = mongoose.model('Resource', ResourceSchema);

var newresource = new Resource({
    activation_dates: [{
        date_add: Date.now()
    }]
});

newresource.save(function(err){
    if(err) throw err;
    newresource.activation_dates.splice(0, 1);
    /**
      * Here I tried
      * newresource.markModified('activation_dates');
      * On update it *DOES* trigger pre save and pre validate
      * But it does nothing to deleted content
    **/ 
    newresource.save(function(err){
        if(err) throw err;
    });
});

Итак, мой вопрос: существует ли чистый способ вызова вспомогательного документа, удаляющего промежуточное программное обеспечение, без продолжения проверки всех предыдущих элементов и сравнения с новыми, чтобы увидеть, какие из них удаляются?

1 ответ

Решение

После небольшого количества исследований я нашел это:

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

Это полный рабочий пример того, как убедиться, что элемент массива не был удален или извлечен. Чтобы проверить наличие изменений, вам понадобятся дальнейшие изменения.

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ResourceSchema = new Schema({
    activation_dates: [subDateSchema]
});

// This virtual permits to store the original array accross the middlewares
ResourceSchema.virtual("original").set(function(item){
    this._original = item;
}).get(function(){
    return this._original;
});

// This middleware checks for a previous version of the "Resource"
ResourceSchema.pre("validate", function(next){
    var self = this;
    mongoose.model("Resource").findById(this._id, function(err, doc){
        if(err) throw err;
        self.original = doc;
        next();
    });
});

// This validation block checks for any modification of the array of sub documents
ResourceSchema.path("activation_dates").validate(function(value){
    var j;
    if(this.original){
        // if the new array is smaller than the original, no need to go further
        if(this.original.activation_dates.length > value.length){
            return false;
        }

        for(var i=0; i < this.original.activation_dates.length; i++){
            j=0;
            // if the array element has been deleted but not pulled out, we need to check it
            if(typeof value[j] == "undefined" || typeof value[j]._id == "undefined"){
                return false;
            }

            while(value.length > j && this.original.activation_dates[i]._id.toString() != value[j]._id.toString()){
                j++;
            }
            if(j == value.length){
                return false;
            }
        }
    }
    return true;
}, "You deleted at least one element of the array");

var Resource = mongoose.model('Resource', ResourceSchema);

var newresource = new Resource({
    activation_dates: [{
        date_add: Date.now()
    }]
});

newresource.save(function(err){
    if(err) throw err;

    newresource.activation_dates.splice(0, 1);
    // OR:
    //delete newresource.activation_dates[0];
    // this line is essential in the case you *delete* but not pull out
    newresource.markModified('activation_dates');

    newresource.save(function(err){
        if(err) throw err;
    });
});

К сожалению, я не смог найти другого решения, кроме как сделать цикл по всем элементам и получить исходный документ.

Другие вопросы по тегам