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

Posted

技术标签:

【中文标题】FindAll 包括更多关于 sequelize 查询的表【英文标题】:FindAll include more tables on sequelize query 【发布时间】:2017-07-28 10:03:47 【问题描述】:

我在我的服务器控制器上有以下查询,我从所有关联表中为我的课程带来了所有数据:

db.Course.findAll(
  include: [
    // model:db.Room, attributes:['id','DisplayLabel'],
    // model:db.Period, attributes:['id','DisplayName'],
     model: db.Subject, attributes: ["id", "Name"] ,
    // model:db.Schedule, attributes:['id','Day','StartHour','EndHour'],
     model: db.Person, where:  id: db.Course.PersonId  
  ]
);

课程模型关联是这样的:

Course.hasMany(models.Schedule);

Course.belongsTo(models.Period);
Course.belongsTo(models.Room);
Course.belongsTo(models.Subject);
Course.belongsTo(models.School);
Course.belongsTo(models.Person);

问题是我无法获取“Person”数据,因为 sql 日志显示连接一直通过与 Person 模型关联的其他表:

verbose: Executing (default): SELECT `Course`.`id`, `Course`.`Scholarship`, `Course`.`Level`, `Course`.`CourseType`, `Course`.`RecordStatus`, `Course`.`DeletedAt`, `Course`.`createdAt`, `Course`.`updatedAt`, `Course`.`PeriodId`, `Course`.`RoomId`, `Course`.`SubjectId`, `Course`.`SchoolId`, `Course`.`PersonId`, `Course`.`CreatedById`, `Course`.`UpdateById`, `Course`.`DeleteById`, `Subject`.`id` AS `Subject.id`, `Subject`.`Name` AS `Subject.Name`, `People`.`id` AS `People.id`, `People`.`RFC` AS `People.RFC`, `People`.`FirstName` AS `People.FirstName`, `People`.`LastName` AS `People.LastName`, `People`.`LastName2` AS `People.LastName2`, `People`.`Phone` AS `People.Phone`, `People`.`Cellphone` AS `People.Cellphone`, `People`.`Email` AS `People.Email`, `People`.`Birthday` AS `People.Birthday`, `People`.`RecordStatus` AS `People.RecordStatus`, `People`.`DeletedAt` AS `People.DeletedAt`, `People`.`createdAt` AS `People.createdAt`, `People`.`updatedAt` AS `People.updatedAt`, `People`.`RoleId` AS `People.RoleId`, `People`.`SchoolId` AS `People.SchoolId`, `People`.`TutorId` AS `People.TutorId`, `People`.`CreatedById` AS `People.CreatedById`, `People`.`UpdateById` AS `People.UpdateById`, `People`.`DeleteById` AS `People.DeleteById`, `People.Task`.`Title` AS `People.Task.Title`, `People.Task`.`Content` AS `People.Task.Content`, `People.Task`.`Grade` AS `People.Task.Grade`, `People.Task`.`OtherDetails` AS `People.Task.OtherDetails`, `People.Task`.`TaskType` AS `People.Task.TaskType`, `People.Task`.`RecordStatus` AS `People.Task.RecordStatus`, `People.Task`.`DeletedAt` AS `People.Task.DeletedAt`, `People.Task`.`createdAt` AS `People.Task.createdAt`, `People.Task`.`updatedAt` AS `People.Task.updatedAt`, `People.Task`.`KardexId` AS `People.Task.KardexId`, `People.Task`.`PersonId` AS `People.Task.PersonId`, `People.Task`.`CourseId` AS `People.Task.CourseId`, `People.Task`.`CreatedById` AS `People.Task.CreatedById`, `People.Task`.`UpdateById` AS `People.Task.UpdateById`, `People.Task`.`DeleteById` AS `People.Task.DeleteById` FROM `Courses` AS `Course` LEFT OUTER JOIN `Subjects` AS `Subject` ON `Course`.`SubjectId` = `Subject`.`id` INNER JOIN (`Tasks` AS `People.Task` INNER JOIN `People` AS `People` ON `People`.`id` = `People.Task`.`PersonId`) ON `Course`.`id` = `People.Task`.`CourseId` AND `People`.`id` = NULL;

就像您看到的那样,它带来了 Task 模型中的列,这是一个源自 Course 和 People 之间的 m:n 关系的表

associate: function(models)
  models.Person.belongsToMany(models.Course, through : Task);
  models.Course.belongsToMany(models.Person, through : Task);

此外,如果我出于调试目的从数据库中删除表,它对另一个 m:n 关系的作用相同。如何从联接中排除它以获取数据?

Model Person,您是否想知道它保存了所有不同的用户:Student、Teacher、Father,并且它有一个具有此 RoleTypes 的 Role Model 外键。这就是为什么我在课程模型中有 PersonId 键,在这种情况下是教师,例如在任务模型中,PersonId 指的是学生用户。

【问题讨论】:

【参考方案1】:

您的查询使用joinTask,因为您在PersonCourse 之间定义了两个关联。第一个是Course.belongsTo(Person),第二个是 m:n 关系。发生的情况是 Sequelize 将其中之一考虑在内 - 它如何知道您想要 belongsTo 关联而不是 m:n?为了省略这种情况,您可以在关联中使用alias

Course.belongsTo(models.Person,  as: 'Teacher' ); // example alias

然后,为了检索带有 TeacherCourse,您必须包含 alias

db.Course.findAll(
    include: [
         model: db.Person, as: 'Teacher' 
    ]
).then((course) => 
    // course with Teacher
);

你可以对 m:n 关系做同样的事情

models.Course.belongsToMany(models.Person,  as: 'Students', through: Task );

然后您将使用 Students 别名来返回给定课程的所有学生。

编辑

为了获得除ModelId 之外的列名,您需要在关联中定义foreignKeyotherKey。在您的情况下,在 CoursePerson 之间的 m:n 关系中,您希望使用 StudentId 而不是 PersonId,您必须使用 otherKey

models.Course.belongsToMany(models.Person,  as: 'Students', through: Task, otherKey: 'StudentId' );

现在连接表将同时包含CourseId(引用Course 表)和StudentId(引用Person 表)。

注意:如果您还在Person 模型上定义了 m:n 关系,请记住添加等效选项 - foreignKey,如下所示:

models.Person.belongsToMany(models.Course,  as: 'Courses', through: Task, foreignKey: 'StudentId' );

【讨论】:

谢谢!这行得通,还有一件事。正如你所说,我试图将别名放在 n:m 关系上:models.Course.belongsToMany(models.Person, as: 'Students', through: Task );但它一直以 PersonId 的形式出现在数据库中,有什么线索吗? 我已经编辑了答案,使用这个解决方案你会得到StudentId而不是PersonId

以上是关于FindAll 包括更多关于 sequelize 查询的表的主要内容,如果未能解决你的问题,请参考以下文章

Sequelize - 仅包括找到一个结果

Sequelize findAll 不是函数

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

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

nodejs中sequelize的where操作符详解,包括举例说明

Sequelize Query FindAll 不过滤