Sequelize:在 findAll 中包含连接表属性包括

Posted

技术标签:

【中文标题】Sequelize:在 findAll 中包含连接表属性包括【英文标题】:Sequelize: Including join table attributes in findAll include 【发布时间】:2017-02-11 13:24:56 【问题描述】:

我目前正在开发一个应用程序,用于管理公司的分支机构和员工,使用 NodeJS、MSSQL 和 Sequilize 作为 ORM。

要求以一种我们可以“回到”过去的日期并查看公司在该特定时间点的状态的方式跟踪某些变化。为了做到这一点,我们使用时间戳initDateendDate)来跟踪我们关心的变化,即分支机构的变化以及员工在活动分支机构之间的流动。每次更改记录时,我们将其endDate 设置为now() 并使用更改和endDate = null 创建新记录,因此每个分支或分支-员工关系的“当前”版本是带有@987654326 的版本@。

我们现在在使用 Sequelize 时面临的问题是:当findAll()ing 我们的员工同时急切加载(即includeing)他们的分支机构时,我们如何为分支机构-员工关系指定endDate?在下面的示例中,我正在查询公司的“当前”状态,所以我要求endDate: null,但这实际上是一个说明我们想要的时间点的参数。

非常感谢您的帮助。任何见解都将不胜感激!

--- 这里我包括模型定义和查询---

分支模型定义:

var BranchModel = db.define<BranchInstance, Branch>('Branch', 
    IdBranch: 
        primaryKey: true,
        type: DataTypes.INTEGER
    ,
    Name: DataTypes.STRING,
    // ... other fields ...
    initDate: DataTypes.DATE,
    endDate: DataTypes.DATE
, 
    timestamps: false,
    classMethods: 
        associate: function (models) 

            Branch.belongsToMany(models.model('Employee'), 
                through: 
                    model: models.model('Branch_Employee')
                ,
                as: 'Employees',
                foreignKey: 'branchId'
            );

            // ... other associations ..

        
    
);

员工模型定义:

var EmployeeModel = db.define<EmployeeInstance, Employee>('Employee', 
    idEmployee: 
        primaryKey: true,
        type: DataTypes.INTEGER
    ,
    Name: DataTypes.STRING,
    // ... other fields ...
    active: DataTypes.BOOLEAN
, 
    timestamps: false,
    defaultScope: 
        where: 
            active: true
        
    ,
    classMethods: 
        associate: function (models) 

            EmployeeModel.belongsToMany(models.model('Branch'), 
                through: 
                    model: models.model('Branch_Employee')
                ,
                foreignKey: 'employeeId'
            );

            // ... other associations ...
        
    
);

连接表定义:

var Branch_Employee = db.define<BranchEmployeeInstance, BranchEmployee>('Branch_Employee', 
    branchId: DataTypes.INTEGER,
    employeeId: DataTypes.INTEGER
    // ... some other attributes of the relation ...
    initDate: DataTypes.DATE,
    endDate: DataTypes.DATE,
, 
    timestamps: false,
    classMethods: 
        associate: function(models) 

            Branch_Employee.belongsTo(models.model('Employee'), 
                as: 'Employee',
                foreignKey: 'employeeId'
            );

            Branch_Employee.belongsTo(models.model('Branch'), 
                as: 'Branch',
                foreignKey: 'branchId'
            );
        
    ,
    instanceMethods: 
        // ... some instance methods ...
    
);

Sequelize 查询以获取每个活跃的员工,急切地加载与他们相关的分支机构:

let employees = await EmployeeModel.findAll(
    logging: true,
    include: [
        model: Branch,
        as: 'Branches',
        where: 
            endDate: null, // this would be [Branches].[endDate] IS NULL

            // i also need the generated query to include:
            // [Branches.Branch_Employee].[endDate] IS NULL

        ,
        required: false
    ]
);

上述查询生成的 SQL,如下所示:

SELECT [Employee].[idEmployee]
,[Employee].[Name]
,[Employee].[active]
,[Branches].[IdBranch] AS [Branches.IdBranch]
,[Branches].[Name] AS [Branches.Name]
,[Branches].[initDate] AS [Branches.initDate]
,[Branches].[endDate] AS [Branches.endDate]
,[Branches.Branch_Employee].[initDate] AS Branches.Branch_Employee.initDate]
,[Branches.Branch_Employee].[endDate] AS [Branches.Branch_Employee.endDate]
,[Branches.Branch_Employee].[branchId] AS Branches.Branch_Employee.branchId]
,[Branches.Branch_Employee].[employeeId] AS [Branches.Branch_Employee.employeeId]
FROM [Employee] AS [Employee]
LEFT OUTER JOIN (
    [Branch_Employee] AS [Branches.Branch_Employee]
    INNER JOIN [Branch] AS [Branches] 
    ON [Branches].[IdBranch] = [Branches.Branch_Employee].[branchId]
) ON [Employee].[idEmployee] = [Branches.Branch_Employee].[employeeId]
AND [Branches].[endDate] IS NULL
WHERE [Employee].[active] = 1;

但是,我实际上需要进一步限制结果集,使其仅包含“当前”的分支机构-员工关系,例如:

[Branches.Branch_Employee].[endDate] IS NULL

【问题讨论】:

【参考方案1】:

我应该更多地感谢 Sequelize 文档,因为通常情况下,它有答案。我将其包括在内,以防其他人正在努力解决这个特定问题:

从Sequelize doc 开始,findAll(options) 函数接受以下选项:

[options.include[].through.where] 连接模型上的 Object Filter 用于 belongsToMany 关系。

这正是我所需要的!希望这会有所帮助。

【讨论】:

感谢您添加您的发现,非常有帮助!

以上是关于Sequelize:在 findAll 中包含连接表属性包括的主要内容,如果未能解决你的问题,请参考以下文章

在 sequelize v6 中包含模型的问题排序 [已解决] - 这不是 sequelize 错误

Spring中如何通过CrudRepository的`findAll()`方法在序列化中包含恢复对象的id?

Sequelize findAll 不是函数

sequelize/sequelize-typescript - 带有 HasMany 的 findAll 返回一个对象而不是数组

使用 Sequelize 获取“TypeError:无法读取未定义的属性‘findAll’”

FindAll 包括更多关于 sequelize 查询的表