首页 > 解决方案 > Sequelize 忽略 UPDATE 方法的关联模型上的 WHERE 条件(不构建查询的 INNER JOIN 部分)

问题描述

我正在尝试在具有主模型和相关模型条件update的模型上运行方法。WHERESequelize 忽略嵌套WHERE条件和整个关联,并生成一个没有该INNER JOIN元素的查询。相关:我想一次更新许多记录,所以单实例方法不是我想要的。

我的查询设置如下所示:

const setInstruction = {
    displayIndex: Sequelize.literal('displayIndex + 1')
};
const updateOptions = {
    where: {
        ID: { [Op.ne]: 1616 },
        displayIndex: { [Op.and]: { [Op.lt]: 7, [Op.gte]: 3 } }
    },
    include: [
        {
            model: models.Component,
            required: true,
            attributes: [],                
            include: [
                {
                    model: models.ObjectType,
                    attributes: [],
                    required: true,
                    where: { objectType: 'Task' }
                }
            ]
        }
    ],
};
return models.UserComponent.update(setInstruction, updateOptions);

它生成这个 SQL 查询:

UPDATE `user_components` SET `displayIndex` = displayIndex + 1, `updatedAt` =? WHERE`ID` != 1616 AND(`displayIndex` < 7 AND`displayIndex` >= 3);

如您所见,INNER JOIN缺少,显然只包括主要WHERE条件。由于某种原因也'updatedAt' =?被添加,不知道为什么。查询运行并执行更新,没有抛出错误,但是由于缺少条件,当然影响了太多记录。

有什么问题?我错过了什么?

updateOptions配置确实在一个findAll方法中工作,并使用 s 生成正确的查询INNER JOIN

我还尝试了不同的语法并将条件放在主WHERE语句中,如下所示: '$component.object_type.objectType$': 'Task' 它适用于findAll,但在更新中抛出错误Unknown column 'component->object_type.objectType' in 'where clause'

我的模型定义如下:

const UserComponent = connectionPool.define('user_component', {
    ID: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    }  
}, {
    defaultScope: {
        attributes: { exclude: ['createdAt', 'updatedAt', 'componentID', 'userID', 'ID'] }
    }
});
const Component = connectionPool.define('component', {
    ID: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    }  
}, {
    defaultScope: {
        attributes: {
            exclude: ['createdAt', 'updatedAt']
        }
    }
}
);
const ObjectType = connectionPool.define('object_type', {
    ID: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    },
    objectType: {
        type: Sequelize.STRING,
        allowNull: false
    }
}, {
    defaultScope: {
        attributes: { exclude: ['createdAt', 'updatedAt', 'ID'] }
    }
});

和协会:

models.Component.belongsTo(models.ObjectType, { foreignKey: 'objectTypeID', onDelete: 'CASCADE' });
models.Component.hasMany(models.UserComponent, { foreignKey: 'componentID', onDelete: 'CASCADE' });
models.UserComponent.belongsTo(models.Component, { foreignKey: 'componentID', onDelete: 'CASCADE' });

如何让 Sequelize 添加INNER JOIN条件?我经历了很多问题和文档,在我看来我做的一切都是正确的。我错过了什么?我会感谢任何帮助。

标签: sequelize.js

解决方案


'update' 方法不支持 'include' 选项。请参阅https://sequelize.org/v5/class/lib/model.js~Model.html#static-method-update。您应该获取要更新的模型的所有 ID(使用 findAll),然后使用 [Op.in] 和 IDs 数组更新它们。

const searchOptions = {
    where: {
        ID: { [Op.ne]: 1616 },
        displayIndex: { [Op.and]: { [Op.lt]: 7, [Op.gte]: 3 } }
    },
    attributes: ['ID'],
    include: [
        {
            model: models.Component,
            required: true,
            attributes: [],                
            include: [
                {
                    model: models.ObjectType,
                    attributes: [],
                    required: true,
                    where: { objectType: 'Task' }
                }
            ]
        }
    ],
};

const modelsToUpdate = await models.UserComponent.findAll(searchOptions)
const updateOptions = {
    where: {
        ID: { [Op.in]: modelsToUpdate.map(x => x.ID) }
    }
}
return models.UserComponent.update(setInstruction, updateOptions);

推荐阅读