Sequelize 基于关联的查找

Posted

技术标签:

【中文标题】Sequelize 基于关联的查找【英文标题】:Sequelize find based on association 【发布时间】:2013-09-21 05:13:36 【问题描述】:

我将如何使用 Sequelize 查找关系中的列满足条件的所有人?

例如查找作者姓氏为“希区柯克”的所有书籍。 book 模式包含与 Author 表的 hasOne 关系。

编辑:我了解如何使用原始 SQL 查询来完成此操作,但正在寻找另一种方法

【问题讨论】:

【参考方案1】:

这是一个工作示例,说明如何使用 Sequelize 通过具有特定姓氏的 Author 获取所有 Books。它看起来比实际复杂得多,因为我正在定义模型、关联它们、与数据库同步(以创建它们的表),然后在这些新表中创建虚拟数据。查找代码中间的findAll,具体查看您所追求的内容。

    module.exports = function(sequelize, DataTypes) 

    var Author = sequelize.define('Author', 

        id: 
            type: DataTypes.INTEGER,
            allowNull: false,
            autoIncrement: true,
            primaryKey: true
        ,
        firstName: 
            type: DataTypes.STRING
        ,
        lastName: 
            type: DataTypes.STRING
        

    )

    var Book = sequelize.define('Book', 

        id: 
            type: DataTypes.INTEGER,
            allowNull: false,
            autoIncrement: true,
            primaryKey: true
        ,
        title: 
            type: DataTypes.STRING
        

    )

    var firstAuthor;
    var secondAuthor;

    Author.hasMany(Book)
    Book.belongsTo(Author)

    Author.sync( force: true )
        .then(function() 
            return Book.sync( force: true );
        )
        .then(function() 
            return Author.create(firstName: 'Test', lastName: 'Testerson');
        )
        .then(function(author1) 
            firstAuthor=author1;
            return Author.create(firstName: 'The Invisible', lastName: 'Hand');
        )
        .then(function(author2) 
            secondAuthor=author2
            return Book.create(AuthorId: firstAuthor.id, title: 'A simple book');
        )
        .then(function() 
            return Book.create(AuthorId: firstAuthor.id, title: 'Another book');
        )
        .then(function() 
            return Book.create(AuthorId: secondAuthor.id, title: 'Some other book');
        )
        .then(function() 
            // This is the part you're after.
            return Book.findAll(
                where: 
                   'Authors.lastName': 'Testerson'
                ,
                include: [
                    model: Author, as: Author.tableName
                ]
            );
        )
        .then(function(books)  
            console.log('There are ' + books.length + ' books by Test Testerson')
        );
  

【讨论】:

这对我不起作用,我认为从 sequelize 2.0 开始,where 子句必须放在包含数组成员中,例如include: [model:..., where:...] 尽管如此,答案给了我希望,这在某种程度上是可能的,所以我寻求解决方案:) 我可以确认,从 Sequelize 2.0 开始,where 子句必须在 include 内,就像:include: [ model: .., where: 'Author.lastName: 'Testerson' ] 你不需要 where 子句中的作者: 'lastName': 'Testerson' where 放入include 会生成这样的查询:LEFT OUTER JOIN Authors ON Books.authorId = Authors.id AND Authors.lastName = 'Testerson',结果与LEFT OUTER JOIN Authors ON Books.authorId = Authors.id ... WHERE Authors.lastName = 'Testerson' 完全不同。我不确定如何使用 sequelize 实现后一个查询。【参考方案2】:

在最新版本的 Sequilize (5.9.0) 中 @c.hill 提出的方法不起作用。

现在您需要执行以下操作:

return Book.findAll(
    where: 
        '$Authors.lastName$': 'Testerson'
    ,
    include: [
        model: Author, as: Author.tableName
    ]
);

【讨论】:

我在哪里可以找到这方面的文档? 我没有找到任何文档,但这就像一个魅力! @lordvcs 这里:sequelize.org/master/manual/… 当我用 Sequelize 花费 2 小时来完成这项工作时,我想念好的老式纯 SQL 分页在此不起作用【参考方案3】:

用于文档!

检查急切加载部分

https://sequelize.org/master/manual/eager-loading.html

以上答案!您可以在以下标题的文档中找到它

顶层的复杂 where 子句

来自文档:

为了获得涉及嵌套列的*** WHERE 子句,Sequelize 提供了一种引用嵌套列的方法:'$nested.column$' 语法。

例如,它可用于将包含模型中的 where 条件从 ON 条件移动到*** WHERE 子句。

User.findAll(
  where: 
    '$Instruments.size$':  [Op.ne]: 'small' 
  ,
  include: [
    model: Tool,
    as: 'Instruments'
  ]
);

生成的 SQL:

SELECT
  `user`.`id`,
  `user`.`name`,
  `Instruments`.`id` AS `Instruments.id`,
  `Instruments`.`name` AS `Instruments.name`,
  `Instruments`.`size` AS `Instruments.size`,
  `Instruments`.`userId` AS `Instruments.userId`
FROM `users` AS `user`
LEFT OUTER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
WHERE `Instruments`.`size` != 'small';

为了更好地理解内部 where 选项(在 include 中使用)、带和不带 required 选项以及使用 $nested.column$ 语法的*** where 之间的所有差异,下面我们有四个示例你:

// Inner where, with default `required: true`
await User.findAll(
  include: 
    model: Tool,
    as: 'Instruments',
    where: 
      size:  [Op.ne]: 'small' 
    
  
);

// Inner where, `required: false`
await User.findAll(
  include: 
    model: Tool,
    as: 'Instruments',
    where: 
      size:  [Op.ne]: 'small' 
    ,
    required: false
  
);

// Top-level where, with default `required: false`
await User.findAll(
  where: 
    '$Instruments.size$':  [Op.ne]: 'small' 
  ,
  include: 
    model: Tool,
    as: 'Instruments'
  
);

// Top-level where, `required: true`
await User.findAll(
  where: 
    '$Instruments.size$':  [Op.ne]: 'small' 
  ,
  include: 
    model: Tool,
    as: 'Instruments',
    required: true
  
);

生成的 SQL,按顺序:

-- Inner where, with default `required: true`
SELECT [...] FROM `users` AS `user`
INNER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
  AND `Instruments`.`size` != 'small';

-- Inner where, `required: false`
SELECT [...] FROM `users` AS `user`
LEFT OUTER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
  AND `Instruments`.`size` != 'small';

-- Top-level where, with default `required: false`
SELECT [...] FROM `users` AS `user`
LEFT OUTER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
WHERE `Instruments`.`size` != 'small';

-- Top-level where, `required: true`
SELECT [...] FROM `users` AS `user`
INNER JOIN `tools` AS `Instruments` ON
  `user`.`id` = `Instruments`.`userId`
WHERE `Instruments`.`size` != 'small';

这让我们很好地了解了加入是如何完成的!

【讨论】:

以上是关于Sequelize 基于关联的查找的主要内容,如果未能解决你的问题,请参考以下文章

在 sequelize 中按关联表值查找总和和分组

node开发

建立Model

sequelize.query() 两次返回相同的结果

在 Sequelize 中将模型的条件与其关联的条件结合起来

是否可以使用 Graphql 和 Sequelize 进行多租户?