javascript - Sequelize : Using "where" inside a child include overrides parent's "where" criteria. 涉及复合主键

标签 javascript node.js sequelize.js

所以,

我有两个表,具有 1:M 关系。它们有两个共同的主键:tenant 和 user_id。

我已经定义了模型关系,顺便说一句,我不确定我是否做得正确,因为我仍然不确定如何处理 Sequelize 上的复合主键。这与我的许多其他查询配合得很好,我认为它会影响问题。

// Sequelize model set-up:
const user = serviceLayerDB.define('user',
    { // Database columns:
        tenant: {
            type: Sequelize.STRING(45),
            primaryKey: true
        },
        user_id: {
            type: Sequelize.STRING(24),
            primaryKey: true
        },
        status: {
            type: Sequelize.STRING(11)
        }
    });

const user_component = serviceLayerDB.define('user_component',
    { // Database columns:
        tenant: {
            type: Sequelize.STRING(45),
            primaryKey: true
        },
        user_id: {
            type: Sequelize.STRING(24),
            primaryKey: true
        },
        component_id: {
            type: Sequelize.STRING(24),
            primaryKey: true
        },
        active: {
            type: Sequelize.BOOLEAN
        }
    });


// Sequelize relationship set-up:
user.hasMany(user_component, { foreignKey: 'user_id' });
user.hasMany(user_component, { foreignKey: 'tenant' });

但是问题出现在我有以下查询时:

// Retrieving user and related components.
function getSubscriptions() {
        let options = {
            where: {
                tenant: 'company_A',
                user_id: '1001'
            },
            include: [{ // Adding components, filtered by "active" value:
                model: user_component,
                where: {
                    active: 1
                },
                required: false
            }]
        };

        user.findAll(options)
            .then(function(data) {
                if (data.length === 0) { // If no data found:
                    console.log('No data found');
                    return;
                }

                // Curate Sequelize result:
                let curatedData = data.map(function(userInstance) { return userInstance.get({ plain: true}) }); // Workaround to be able to perform .get().
                console.log(JSON.stringify(curatedData, null, 2));
            })
            .catch(function(error) {
                console.log('critical', 'Failed to find data in database. Error: ' + error);
            })
}


// Execute:
getSubscriptions();

我想要的是找到用户及其组件,但仅限于 active 值设置为 1 的组件。它不起作用:结果是同一组下每个将 active 值设置为 1 的组件“tenant”,子项包含忽略我们在父项中指示的“user_id”

我认为这与我的复合主键有关吗?如何以最优雅的方式解决这个问题?

最佳答案

当您将一个模型多次关联到另一个模型时,您必须使用别名。 例如:

user.hasMany(user_component, { foreignKey: 'user_id', as: 'UserComponents' });
user.hasMany(user_component, { foreignKey: 'tenant', as: 'TenantComponents' });

然后您应该决定要执行包含操作的确切关联: 通过 user_id 字段进行关联

let options = {
            where: {
                tenant: 'company_A',
                user_id: '1001'
            },
            include: [{ // Adding components, filtered by "active" value:
                model: user_component,
                as: 'UserComponents'
                where: {
                    active: 1
                },
                required: false
            }]
        };

租户字段关联

let options = {
            where: {
                tenant: 'company_A',
                user_id: '1001'
            },
            include: [{ // Adding components, filtered by "active" value:
                model: user_component,
                as: 'TenantComponents'
                where: {
                    active: 1
                },
                required: false
            }]
        };

如果您希望两个子集合都具有 active: 1 条件,您可以执行以下操作:

let options = {
            where: {
                tenant: 'company_A',
                user_id: '1001'
            },
            include: [{ // Adding components, filtered by "active" value:
                model: user_component,
                as: 'UserComponents'
                where: {
                    active: 1
                },
                required: false,
                separate: true
            }, { // Adding components, filtered by "active" value:
                model: user_component,
                as: 'TenantComponents'
                where: {
                    active: 1
                },
                required: false,
                separate: true
            }]
        };

请注意separate: true选项:该选项告诉sequielize对子项进行单独的查询。 如果您希望获取的不是所有用户,而是仅具有事件组件的用户(哪些:通过 user_id 或租户字段?),您应该在 include 中设置 required: true 。但在这种情况下,不要包含与 required: true 的两个关联。这会导致 SQL 查询结果中的记录数量成倍增加,并消耗更多内存。

关于javascript - Sequelize : Using "where" inside a child include overrides parent's "where" criteria. 涉及复合主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60247630/

相关文章:

javascript - ASP.Net Razor Pages - 如何将 json 从 razor 页面返回到 javascript $.getJson?

javascript - Node 和 knex - 填充中间表 Promise 问题

node.js - Browserify by Grunt.js watch

mysql - 为什么在 hh/mm/ss 不同的日期之间 Sequelize 返回空

sequelize.js - Sequelize - 包含带有字符串名称的嵌套属性/关系

javascript - es6 中的默认值不适用于箭头函数

javascript - 设计 Javascript 验证方法

node.js - 如何在mongodb的node.js应用程序中包含和使用connection.js文件

javascript - 如何导出 Reflect.defineProperty()?

javascript - 为什么对表格进行排序后单击事件处理程序不起作用