【问题标题】:mongoose findOneAndSave and pre hook, and setting an initial value (addedOn date)mongoose findOneAndSave 和 pre hook,并设置一个初始值( addedOn 日期)
【发布时间】:2016-05-14 11:25:06
【问题描述】:

我是 mongoose 的新手,老实说还有大量的阅读工作要做,但我正在做一个小型宠物项目,该项目可以读取和写入 mongo db。在这种情况下,我想使用 mongoose 来确保一致的文档模型。

问题在于确保插入和更新操作中的默认值独立。特别是,我分别指的是 addedOn 和 updatedOn 字段。我要求持久化的方法是 findOneAndUpdate,它现在支持中间件挂钩(从 4.0 开始)。

我能够使基本挂钩工作(每次都应用 updatedOn 日期),但无法弄清楚如何为默认 addOn 的插入案例添加支持(猫鼬方式)。这是简单的模式和钩子(用于处理插入和更新):

const TestSchema = new Schema({
    id               : ObjectId,
    name             : String,
    addedOn          : { type: Date, default: Date.now },
    updatedOn        : { type: Date, default: Date.now }
});


TestSchema.pre('findOneAndUpdate', function(next) {
    console.log('hook::findOneAndUpdate')
    // update defaults
    this.update({addedOn: {$exists:true}},{
        $set: {
            updatedOn: new Date()
        }
    })
    // insert defaults
    this.update({addedOn: {$exists:false}},{
        $set: {
            addedOn: new Date(),
            updatedOn: new Date()
        }
    })
    next();
});

不足为奇(因为它确实是赃物)它不起作用。每次运行应用程序时都会插入一行。如果向更新方法添加条件会覆盖默认匹配(尚未挖掘源),则会出现这种情况。

这是我对单独更新情况的初始 sn-p,它找到了行并正确更新,但如上所述无法处理 addedOn(它会每次都更新)

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

驱动所有这一切的是这个 sn-p(以使代码尽可能接近我正在开发的应用程序的民间故事实现的习语)

mongoose.connect('mongodb://localhost/network');

const model = mongoose.model('TestSchema', TestSchema)
const schema = TestSchema
const collection = model

const findOneAndUpdate = (collection) => {
    return (criteria, record) => {

        return new Task((reject, resolve) => {
            const callback = (error, data) => {
                if (error) {
                    reject(error)
                }
                else {
                    resolve(data)
                }
            }

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

    }
}
const upsert = findOneAndUpdate(collection)
upsert({name: "me"}, {name: "me"}).fork(console.log, console.error)

我可以修改我的 findOneAndUpdate 函数来添加 addedOn - 但我真的很想正确使用 mongoose 钩子。

【问题讨论】:

    标签: node.js mongodb mongoose mongoose-middleware


    【解决方案1】:

    这里有一个答案,虽然它需要在 findOne 和更新之后进行第二次“保存”:

    const mongoose = require('mongoose')
    
    const  Schema = mongoose.Schema
        , ObjectId = Schema.ObjectId
        , Task = require('data.task') ;
    
    const TestSchema = new Schema({
        id               : ObjectId,
        name             : String,
        genre: {type: String, default: 'Action'},
        addedOn          : { type: Date, default: Date.now, setDefaultsOnInsert: true },
        updatedOn        : { type: Date, default: Date.now }
    });
    
    
    TestSchema.pre('findOneAndUpdate', function(next) {
        console.log('hook::findOneAndUpdate')
        this.update({},{
            $set: {
                updatedOn: new Date()
            }
        })
        next();
    });
    
    
    
    mongoose.connect('mongodb://localhost/network');
    
    const model = mongoose.model('TestSchema', TestSchema)
    
    const 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)
            })
    
        }
    }
    const upsert = findOneAndUpdate(model)
    upsert({name: "me"}, {name: "me"}).fork(console.log, console.error)
    

    我不喜欢它...但它有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      相关资源
      最近更新 更多