Sequelize:在创build和更新之前计算值

我的问题类似于保存前的Sequelize计算值 ,但不完全相同。

我也有一个模型,其中一个字段将被设置,另一个字段将不会被设置,但应该在每次对数据库执行保存操作之前进行计算。 我试图通过使用钩子来实现这一点。

var Foo = sequelize.define( 'foo', { bar: { type: Sequelize.TEXT, allowNull: false }, baz: { type: Sequelize.TEXT, allowNull: false } }, { freezeTableName: true, timestamps: false, hooks: { // beforeCreate: setBaz // beforeUpdate: setBaz beforeValidate: setBaz } } ); function setBaz(foo) { foo.baz = foo.bar + "_baz"; } 

这适用于创build而不是更新现有的元素。

 Foo.create({bar: "bar"}); 

correclty创build以下语句

 INSERT INTO "foo" ("id","bar","baz") VALUES (DEFAULT,'bar','bar_baz') RETURNING *; 

然而,

 Foo.findOne({where: {id: 1}}) .then(function(foo) { return foo.update({bar: "foobar"}); }); 

导致这些陈述

 SELECT "id", "bar", "baz" FROM "foo" AS "foo" WHERE "foo"."id" = 1; UPDATE "foo" SET "bar"='foobar' WHERE "id" = 1 

显然只是为bar设置新的值。

以这种方式logging更改时

 function setBaz(foo) { console.log(foo); foo.baz = foo.bar + "_baz"; console.log(foo); } 

我可以看到该函数被执行并且值设置正确。 之前:

 dataValues: { id: 1, bar: 'foobar', baz: 'bar_baz' }, _previousDataValues: { id: 1, bar: 'bar', baz: 'bar_baz' }, _changed: { bar: true }, 

后:

 dataValues: { id: 1, bar: 'foobar', baz: 'foobar_baz' }, _previousDataValues: { id: 1, bar: 'bar', baz: 'bar_baz' }, _changed: { bar: true, baz: true }, 

另外更改的标志设置正确。

我以前尝试使用beforeCreatebeforeUpdate挂钩,但这会导致创build案例中的错误,这似乎是合理的。

 Unhandled rejection SequelizeValidationError: notNull Violation: baz cannot be null 

使用get / setDataValue也不会改变任何东西

 foo.setDataValue("baz", foo.getDataValue("bar") + "_baz"); 

钩子上的文档是非常稀疏的,所以任何帮助表示赞赏。 我怎样才能得到sequelize也更新计算字段?

看起来像sequelize是在调用validation钩子之前计算更改的字段。 为了覆盖这个,你可以改变传递的选项中字段

 function setBaz(foo, o) { if(_.contains(o.fields, "bar")) { // if bar was not changed, nothing has to be done foo.setDataValue("baz", foo.getDataValue("bar") + "_baz"); if(!_.contains(o.fields, "baz")) { o.fields.push("baz"); // Adjust the fields to be saved _.pull(o.skip, "baz"); // Also adjust the skipped fields, for consistency } } return Promise.resolve(o); }