Sequelize使用LEFT JOIN而不是嵌套的INNER JOIN进行多对多关联

时间:2017-10-10 14:17:31

标签: mysql sequelize.js

我在Sequelize(MySQL)中设置了三个模型 - Book,Author和Book_author(连接表)。我设置了以下关联:

Book.belongsToMany(Author,
  {
    through: Book_author,
    foreignKey: 'book_id'
  }
);
Author.belongsToMany(Book,
  {
    through: Book_author,
    foreignKey: 'author_id'
  }
);

当我在Book模型上尝试findAll查询时,如下所示......

Book.findAll({
    include: [
      { model: Author
      }
    ]
  }).then(bookList => {
    // do something with the bookList
});

...它生成一个具有以下结构的原始SQL查询(我删除了各个属性以保持简洁):

SELECT book.*, author.* FROM book
LEFT JOIN (author
    INNER JOIN book_author
    ON author.author_id = book_author.author_id)
ON book.book_id = book_author.book_id;

然而,嵌套的INNER JOIN使我的查询变慢。单独测试原始SQL查询时也是如此,因此它不是Sequelize问题。为了缓解这种情况,我希望原始SQL查询只使用LEFT JOIN,如下所示:

SELECT book.*, author.* FROM book
LEFT JOIN book_author
ON book.book_id = book_author.book_id
LEFT JOIN author
ON author.author_id = book_author.author_id;

我如何更改Sequelize模型和/或findAll includes属性才能获得此结果?我尝试在required: false属性中使用includes,但这只会影响外部JOIN,而不会影响嵌套的JOIN。有没有办法在不使用sequelize.query的情况下执行此操作?谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

您可以使用两个belongsTo关联而不是belongsToMany

Book.hasMany(BookAuthor);
BookAuthor.belongsTo(Author);

const bookList = await Book.findAll({
    include: [{
        model: BookAuthor,
        required: false,
        include: [{
            model: Author,
            required: false 
        }]
    }]
});