使用 Sequelize 更新关联模型中的属性 [英] Updating attributes in associated models using Sequelize

查看:77
本文介绍了使用 Sequelize 更新关联模型中的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to update attributes on both the parent model and the associated models all in one go? I am having trouble getting it to work and haven't been able to find any full examples. I'm not sure if it's something wrong with my code or if it wasn't intended to work the way I would expect. I tried adding the onUpdate : 'cascade' to my hasMany definition, but that didn't seem to do anything.

型号:

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
    };
}

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

Retrieving the filter and trying to update an attribute on the associated FilteredContent object:

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();
});

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

This results in only attributes in the Filter object being updated. How do I get it to also update the attributes in FilteredContent?

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

Also, is the sequelize.sync() necessary after defining my models? I'm not clear on what exactly it is supposed to do. I am able to retrieve my object with associations without it. I added it to my code in desperation to get the updates working, but I'm not sure if it's actually necessary.

谢谢

推荐答案

针对您的问题:

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

When you eagerly load FilteredContent (using include), a model instance is already built, so there is no reason to call build. Something along the lines of this should do what you want:

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

关于您整体发布的代码的几点说明:

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

编辑以回答您的评论:

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

You cannot do a single function call that will update both filter and filteredcontent, but you don't have to do the updates in sequence either. You can issue all the update commands without waiting for them to complete.

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) {

})

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

In this way all queries will run in parallel, and your then function will be called when all of them have completed. Notice that I've used spread here to turn the array returned from Promise.all into separate arguments.

这篇关于使用 Sequelize 更新关联模型中的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆