0

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

问题在于独立地确保插入和更新操作中的默认值。特别是,我分别指的是 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();
});

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

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

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 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 - 但我真的很想正确使用猫鼬钩子。

4

1 回答 1

0

好吧,这是一个答案,尽管在 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)

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

于 2016-02-07T18:06:23.547 回答