OK. So, first of all, let's load all tasks with their associated user.

    1. Task.findAll({ include: [ User ] }).then(tasks => {
    2. console.log(JSON.stringify(tasks))
    3. /*
    4. [{
    5. "name": "A Task",
    6. "id": 1,
    7. "createdAt": "2013-03-20T20:31:40.000Z",
    8. "updatedAt": "2013-03-20T20:31:40.000Z",
    9. "userId": 1,
    10. "user": {
    11. "name": "John Doe",
    12. "id": 1,
    13. "createdAt": "2013-03-20T20:31:45.000Z",
    14. "updatedAt": "2013-03-20T20:31:45.000Z"
    15. }
    16. }]
    17. */
    18. })

    Notice that the accessor (the User property in the resulting instance) is singular because the association is one-to-something.

    Next thing: Loading of data with many-to-something associations!

    1. User.findAll({ include: [ Task ] }).then(users => {
    2. console.log(JSON.stringify(users))
    3. /*
    4. [{
    5. "name": "John Doe",
    6. "id": 1,
    7. "createdAt": "2013-03-20T20:31:45.000Z",
    8. "updatedAt": "2013-03-20T20:31:45.000Z",
    9. "tasks": [{
    10. "name": "A Task",
    11. "id": 1,
    12. "createdAt": "2013-03-20T20:31:40.000Z",
    13. "updatedAt": "2013-03-20T20:31:40.000Z",
    14. "userId": 1
    15. }]
    16. }]
    17. */
    18. })

    Notice that the accessor (the Tasks property in the resulting instance) is plural because the association is many-to-something.

    If an association is aliased (using the as option), you must specify this alias when including the model. Notice how the user's Tools are aliased as Instruments above. In order to get that right you have to specify the model you want to load, as well as the alias:

    1. User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(users => {
    2. console.log(JSON.stringify(users))
    3. /*
    4. [{
    5. "name": "John Doe",
    6. "id": 1,
    7. "createdAt": "2013-03-20T20:31:45.000Z",
    8. "updatedAt": "2013-03-20T20:31:45.000Z",
    9. "Instruments": [{
    10. "name": "Toothpick",
    11. "id": 1,
    12. "createdAt": null,
    13. "updatedAt": null,
    14. "userId": 1
    15. }]
    16. }]
    17. */
    18. })
    1. User.findAll({ include: ['Instruments'] }).then(users => {
    2. console.log(JSON.stringify(users))
    3. /*
    4. [{
    5. "name": "John Doe",
    6. "id": 1,
    7. "createdAt": "2013-03-20T20:31:45.000Z",
    8. "updatedAt": "2013-03-20T20:31:45.000Z",
    9. "Instruments": [{
    10. "name": "Toothpick",
    11. "id": 1,
    12. "createdAt": null,
    13. "updatedAt": null,
    14. "userId": 1
    15. }]
    16. }]
    17. */
    18. User.findAll({ include: [{ association: 'Instruments' }] }).then(users => {
    19. console.log(JSON.stringify(users))
    20. [{
    21. "name": "John Doe",
    22. "id": 1,
    23. "createdAt": "2013-03-20T20:31:45.000Z",
    24. "updatedAt": "2013-03-20T20:31:45.000Z",
    25. "Instruments": [{
    26. "name": "Toothpick",
    27. "id": 1,
    28. "createdAt": null,
    29. "updatedAt": null,
    30. "userId": 1
    31. }]
    32. }]
    33. */
    34. })

    When eager loading we can also filter the associated model using where. This will return all Users in which the where clause of Tool model matches rows.

    When an eager loaded model is filtered using include.where then include.required is implicitly set totrue. This means that an inner join is done returning parent models with any matching children.

    To move the where conditions from an included model from the ON condition to the top level WHERE you can use the '$nested.column$' syntax:

    1. User.findAll({
    2. where: {
    3. '$Instruments.name$': { [Op.iLike]: '%ooth%' }
    4. },
    5. include: [{
    6. model: Tool,
    7. as: 'Instruments'
    8. }]
    9. }).then(users => {
    10. console.log(JSON.stringify(users));
    11. /*
    12. [{
    13. "name": "John Doe",
    14. "id": 1,
    15. "createdAt": "2013-03-20T20:31:45.000Z",
    16. "updatedAt": "2013-03-20T20:31:45.000Z",
    17. "Instruments": [{
    18. "name": "Toothpick",
    19. "id": 1,
    20. "createdAt": null,
    21. "updatedAt": null,
    22. "userId": 1
    23. }]
    24. }],
    25. [{
    26. "name": "John Smith",
    27. "id": 2,
    28. "createdAt": "2013-03-20T20:31:45.000Z",
    29. "updatedAt": "2013-03-20T20:31:45.000Z",
    30. "Instruments": [{
    31. "name": "Toothpick",
    32. "id": 1,
    33. "createdAt": null,
    34. "updatedAt": null,
    35. "userId": 1
    36. }]
    37. }],
    38. */

    Including everything

    To include all attributes, you can pass a single object with all: true:

    1. User.findAll({ include: [{ all: true }]});

    In case you want to eager load soft deleted records you can do that by setting include.paranoid to false

    1. User.findAll({
    2. include: [{
    3. model: Tool,
    4. where: { name: { [Op.like]: '%ooth%' } },
    5. paranoid: false // query and loads the soft deleted records
    6. }]
    7. });

    Ordering Eager Loaded Associations

    1. Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] });
    2. Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] });
    3. Company.findAll({
    4. include: [ { model: Division, as: 'Div' } ],
    5. order: [ [ { model: Division, as: 'Div' }, 'name' ] ]
    6. });
    7. Company.findAll({
    8. include: [ { model: Division, as: 'Div' } ],
    9. order: [ [ { model: Division, as: 'Div' }, 'name', 'DESC' ] ]
    10. });
    11. Company.findAll({
    12. include: [ { model: Division, include: [ Department ] } ],
    13. order: [ [ Division, Department, 'name' ] ]

    In the case of many-to-many joins, you are also able to sort by attributes in the through table.

    You can use nested eager loading to load all related models of a related model:

    1. User.findAll({
    2. include: [
    3. {model: Tool, as: 'Instruments', include: [
    4. {model: Teacher, include: [ /* etc */]}
    5. ]}
    6. ]
    7. }).then(users => {
    8. console.log(JSON.stringify(users))
    9. /*
    10. [{
    11. "name": "John Doe",
    12. "id": 1,
    13. "createdAt": "2013-03-20T20:31:45.000Z",
    14. "updatedAt": "2013-03-20T20:31:45.000Z",
    15. "Instruments": [{ // 1:M and N:M association
    16. "name": "Toothpick",
    17. "id": 1,
    18. "createdAt": null,
    19. "updatedAt": null,
    20. "userId": 1,
    21. "Teacher": { // 1:1 association
    22. "name": "Jimi Hendrix"
    23. }
    24. }]
    25. }]
    26. */
    27. })

    This will produce an outer join. However, a where clause on a related model will create an inner join and return only the instances that have matching sub-models. To return all parent instances, you should add required: false.

    1. User.findAll({
    2. include: [{
    3. model: Tool,
    4. as: 'Instruments',
    5. include: [{
    6. model: Teacher,
    7. where: {
    8. school: "Woodstock Music School"
    9. },
    10. required: false
    11. }]
    12. }]
    13. }).then(users => {
    14. /* ... */
    15. })

    The query above will return all users, and all their instruments, but only those teachers associated with Woodstock Music School.

    Include all also supports nested loading:

    1. User.findAll({ include: [{ all: true, nested: true }]});

    Use right join for association

    Note: right is only respected if required is false.

    1. User.findAll({
    2. include: [{
    3. model: Tool // will create a left join
    4. }]
    5. });
    6. User.findAll({
    7. include: [{
    8. model: Tool,
    9. right: true // will create a right join
    10. }]
    11. });
    12. User.findAll({
    13. include: [{
    14. model: Tool,
    15. required: true,
    16. right: true // has no effect, will create an inner join
    17. }]
    18. });
    19. User.findAll({
    20. include: [{
    21. model: Tool,
    22. where: { name: { [Op.like]: '%ooth%' } },
    23. right: true // has no effect, will create an inner join
    24. }]
    25. });
    26. User.findAll({
    27. include: [{
    28. model: Tool,
    29. where: { name: { [Op.like]: '%ooth%' } },
    30. required: false
    31. right: true // because we set `required` to false, this will create a right join
    32. }]