使用Sequelize更新关联模型中的属性

jsp*_*rks 19 node.js sequelize.js

是否可以一次性更新父模型和关联模型的属性?我无法让它工作,也无法找到任何完整的例子.我不确定我的代码是否有问题,或者它是否打算以我期望的方式工作.我尝试将onUpdate:'cascade'添加到我的hasMany定义中,但这似乎没有做任何事情.

楷模:

module.exports = function( sequelize, DataTypes ) {
var Filter = sequelize.define( 'Filter', {
    id : {
            type : DataTypes.INTEGER,
            autoIncrement : true,
            primaryKey : true
         },
        userId : DataTypes.INTEGER,
        filterRetweets : DataTypes.BOOLEAN,
        filterContent : DataTypes.BOOLEAN
    },
    {
        tableName : 'filter',
        timestamps : false
    }
);

var FilteredContent = sequelize.define( 'FilteredContent', {
        id : {
                type : DataTypes.INTEGER,
                autoIncrement : true,
                primaryKey : true
        },
        filterId : {
                        type : DataTypes.INTEGER,
                        references : "Filter",
                        referenceKey : "id"
        },
        content : DataTypes.STRING
    },
    {
        tableName : "filteredContent",
        timestamps : false
    }
);

Filter.hasMany( FilteredContent, { onUpdate : 'cascade', as : 'filteredContent', foreignKey : 'filterId' } );
sequelize.sync();

    return {
        "Filter" : Filter,
        "FilteredContent" : FilteredContent
    };
}
Run Code Online (Sandbox Code Playgroud)

检索过滤器并尝试更新关联的FilteredContent对象上的属性:

Filter.find({   where: { id: 3 }, 
            include: [ { model : FilteredContent, as : 'filteredContent' } ] 
}).success ( function( filter ) {
    var filteredContent = FilteredContent.build( {
        filterId : filter.id,
        id : 2,
        content : 'crap'
    });
    filter.save();
});
Run Code Online (Sandbox Code Playgroud)

这导致只更新Filter对象中的属性.如何让它也更新FilteredContent中的属性?

另外,定义模型后是否需要sequelize.sync()?我不清楚应该做什么.没有它我可以用关联检索我的对象.我绝望地将它添加到我的代码中以使更新正常工作,但我不确定它是否真的有必要.

谢谢

Jan*_*ier 25

对于你的问题:

当您急切地加载FilteredContent(使用include)时,已经构建了一个模型实例,因此没有理由调用build.根据这一点,你应该做你想做的事情:

Filter.find({
  where: { id: 3 }, 
  include: [ { model : FilteredContent, as : 'filteredContent' } ] 
}).then ( function( filter ) {
  return filter.filteredContent[0].updateAttributes({
    content: 'crap'
  })
}).then(function () {
  // DONE! :)
});
Run Code Online (Sandbox Code Playgroud)

关于您发布的代码的几个指针:

  • sequelize.sync为模型创建数据库表(如果它们尚不存在).如果您的表已存在,则不需要执行此操作
  • sequelize.sync是一个异步操作,因此不建议在不附加回调的情况下执行sequelize.sync.此外,您似乎在模型定义中进行同步 - 您应该只执行一次,最好是在您定义模型的位置.
  • 看起来您在一个文件中定义了几个模型 - 您应该只在每个文件中定义一个模型.可以通过在FilterContent文件中执行sequelize.import([过滤器模型的路径])或在将模型导入应用程序的位置执行所有关联来设置关联.

编辑以回答您的评论:

您不能执行将更新过滤器和过滤内容的单个函数调用,但您也不必按顺序执行更新.您可以发出所有更新命令,而无需等待它们完成.

Filter.find({
  where: { id: 3 }, 
  include: [ { model : FilteredContent, as : 'filteredContent' } ] 
}).then ( function( filter ) {
  return Promise.all([
    filter.updateAttributes({}),
    filter.filteredContent.map(fc => fc.updateAttributes({}))
  ]);
}).spread(function (filter, filteredContents) {

})
Run Code Online (Sandbox Code Playgroud)

通过这种方式,所有查询都将并行运行,并且当所有查询都已完成时,将调用then函数.请注意,我在spread这里使用将返回的数组Promise.all转换为单独的参数.