Sequelize find based on association

前端 未结 3 1525
时光说笑
时光说笑 2020-12-23 19:53

How would I use Sequelize to find all people where a column in the relation satisfies a condition?

An example would be to find all Books whose author\'s last name is

相关标签:
3条回答
  • 2020-12-23 20:16

    In the newest version of Sequilize (5.9.0) the method proposed by @c.hill does not work.

    Now you need to do the following:

    return Book.findAll({
        where: {
            '$Authors.lastName$': 'Testerson'
        },
        include: [
            {model: Author, as: Author.tableName}
        ]
    });
    
    0 讨论(0)
  • 2020-12-23 20:17

    Here's a working sample of how to user Sequelize to get all Books by an Author with a certain last name. It looks quite a bit more complicated than it is, because I am defining the Models, associating them, syncing with the database (to create their tables), and then creating dummy data in those new tables. Look for the findAll in the middle of the code to see specifically what you're after.

        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')
            });
      }
    
    0 讨论(0)
  • 2020-12-23 20:29

    For documentation!

    Check the eager loading section

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

    For the above answers! You can find it in the doc at the following title

    Complex where clauses at the top-level

    From the doc:

    To obtain top-level WHERE clauses that involve nested columns, Sequelize provides a way to reference nested columns: the '$nested.column$' syntax.

    It can be used, for example, to move the where conditions from an included model from the ON condition to a top-level WHERE clause.

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

    Generated 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';
    

    The $nested.column$ syntax also works for columns that are nested several levels deep, such as $some.super.deeply.nested.column$. Therefore, you can use this to make complex filters on deeply nested columns.

    For a better understanding of all differences between the inner where option (used inside an include), with and without the required option, and a top-level where using the $nested.column$ syntax, below we have four examples for you:

    // 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
      }
    });
    

    Generated SQLs, in order:

    -- 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';
    

    And that give us a good look how the join's are done!

    0 讨论(0)
提交回复
热议问题