【问题标题】:Mongoose Pre Save hook on Parent Object not executing未执行父对象上的猫鼬预保存挂钩
【发布时间】:2016-02-26 19:40:56
【问题描述】:

我不熟悉 mongoose 作为更新 Mongo 的方法。我正在使用 nmap 来映射我的网络并提供对打开的服务器和端口的一些可见性(作为更大策略的一部分)。这部分策略还从 CHEF 和​​ vSphere 中提取信息,这些信息都在 GUI 中链接在一起。这些部分只是简单的单级对象并且工作正常,但是 NMAP 部分有一个父/子对象模型。对象模型有一个 Server 对象和一个 Port 对象——它们都具有 addedOn 和 updatedOn 日期。

不幸的是,用于预保存的猫鼬钩子仅针对子对象(每个子对象)而不是针对父对象触发 - 尽管父对象正在保存。 我真的希望父对象也有 addedOn 和 updatedOn 日期。我似乎无法弄清楚。提前致谢

免责声明,下面的代码是从一个以民间故事、ramda 和无点形式编写的大型应用程序中截取的。

NodeJs 5.1,猫鼬 4.4.1

port.js 文件

const mongoose = require('mongoose');

const  Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

const PortSchema = new Schema({
    id               : ObjectId,
    port             : String,
    protocol         : String,
    application      : String,
    addedOn          : { type: Date, default: Date.now, setDefaultsOnInsert: true },
    updatedOn        : { type: Date, default: Date.now }
});

PortSchema.pre('save', function(next){
    this.update({},{
        $set: {
            updatedOn: new Date()
        }
    })
    next();
});

module.exports.model = mongoose.model('Port', PortSchema)
module.exports.schema = PortSchema

server.js 文件

const mongoose = require('mongoose');
const PortSchema = require('./port').schema

const  Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

const ServerSchema = new Schema({
    id               : ObjectId,
    address          : String,
    addressType      : String,
    ports            : [PortSchema],
    addedOn          : { type: Date, default: Date.now, setDefaultsOnInsert: true },
    updatedOn        : { type: Date, default: Date.now }
});

ServerSchema.pre('save', function(next){
    this.update({},{
        $set: {
            updatedOn: new Date()
        }
    })
    next();
});


module.exports.model = mongoose.model('Server', ServerSchema)
module.exports.schema = ServerSchema

在我的应用程序中插入代码

// nmapUpsert :: (criteria, {}) => Task {ok :: int, ...}
const nmapUpsert = adapt.findOneAndUpdate(Server)


// persist :: [{address :: string, ...}] => [Task {ok :: int, ...}]
const persistNmap = R.map((data) => {
    return nmapUpsert({ "address": data.address }, data)
})

这是我的模型 -> 任务 upsert 适配器 (adapt.findOneAndUpdate)

module.exports.findOneAndUpdate = (originalModel) => {
    return (criteria, record) => {

        return new Task((reject, resolve) => {
            const callback = (error, updatedModel) => {
                if (error) {
                    reject(error)
                }
                else {
                    if(!updatedModel) {
                        resolve(null)
                    }else {
                        // this looks to be required to apply defaults from the Schema
                        updatedModel.save((error) => {
                            if (error) {
                                reject(error)
                            }
                            resolve(updatedModel)
                        })
                    }

                }
            }

            originalModel.findOneAndUpdate(criteria, record, {upsert: true}, callback)
        })

    }
}

诚然,最后一个函数有点笨拙 - 但我只是想在清理它之前弄清楚这一点。

【问题讨论】:

  • pre-save 钩子不在update 上运行。你应该可以添加一个pre-update 钩子。让我知道这是否有效。
  • @Mike 更新挂钩不起作用,但我将 Server.js 上的挂钩更改为“findOneAndUpdate”挂钩,这似乎在该层有效。现在底层端口没有更新。我需要对此进行调查。

标签: node.js mongodb mongoose


【解决方案1】:

如果我将钩子更改为 findOneAndUpdate,我会得到更好的行为。服务器对象在插入时获取 addedOn(以及 updatedOn),然后仅更新 updatedOn。不幸的是,整个 Ports 对象集合都被替换了——即使在更新时也是如此——并且此时 addedOn 和 updatedOn 都得到了更新。

port.js 文件

const mongoose = require('mongoose');

const  Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

const PortSchema = new Schema({
    id               : ObjectId,
    port             : String,
    protocol         : String,
    application      : String,
    addedOn          : { type: Date, default: Date.now, setDefaultsOnInsert: true },
    updatedOn        : { type: Date, default: Date.now }
});

PortSchema.pre('findOneAndUpdate', function(next){
    this.update({},{
        $set: {
            updatedOn: new Date()
        }
    })
    next();
});

module.exports.model = mongoose.model('Port', PortSchema)
module.exports.schema = PortSchema

server.js 文件

const mongoose = require('mongoose');
const PortSchema = require('./port').schema

const  Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

const ServerSchema = new Schema({
    id               : ObjectId,
    address          : String,
    addressType      : String,
    ports            : [PortSchema],
    addedOn          : { type: Date, default: Date.now, setDefaultsOnInsert: true },
    updatedOn        : { type: Date, default: Date.now }
});

ServerSchema.pre('findOneAndUpdate', function(next){
    this.update({},{
        $set: {
            updatedOn: new Date()
        }
    })
    next();
});


module.exports.model = mongoose.model('Server', ServerSchema)
module.exports.schema = ServerSchema

【讨论】:

    猜你喜欢
    • 2017-08-19
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 2018-06-28
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    相关资源
    最近更新 更多