Where clause based on a column in an associated model

Viewed 20

I'd like to conditionally add a where clause to my query so that it filters the results by a column in an associated model, of an associated model.

ie: Application => Job => filter by column of Company

currently I can only filter by a column in the Job table

These are the associations:

Applicant.belongsToMany(Job, {through: Application})
Job.belongsToMany(Applicant, { through: Application });

// Associations so the Application table can be directly queried
Application.belongsTo(Job, { foreignKey: { name: 'jobId' }});
Application.belongsTo(Applicant, { foreignKey: { name: 'applicantId' } });

Company.hasMany(Job, { foreignKey: { name: 'companyId', allowNull: false} });
Job.belongsTo(Company, { foreignKey: { name: 'companyId', allowNull: false} });

As above, I'd like to return all the applications where the column name in the Company model is similar to a searchTerm

I can currently return only the relevant applications where the column title in the Job model matches, but if I try to filter by a more deeply nested model, like Company it doesn't work

Here's how I add a where clause to the options object to filter by job.title:

   const options = {
      order: // ...      
      distinct: true,
      attributes //... 
      include: [
        {                               
          model: Job,
          include: [ 
            { 
              model: Company,
              attributes: [ 'id', 'name' ],
              include: [
                {
                  model: Contact,
                  separate: true,
                  include: [{
                    model: Person,
                    attributes: [ 'firstName', 'lastName', 'phone', 'email' ]
                  }]
                }
              ]
            } 
          ]
        },
        {
          model: Applicant,
          include: [ 
            {
              model: Person,
              attributes: [ 'id', 'firstName', 'lastName', 'email', 'phone', 'createdAt' ]
            } 
          ],
        }
      ];
    }



if(x) options.include[0].where = { title: { [Op.like]: `%${searchTerm}%` } };
const results = Application.findAll(options)

This returns only the applications that have jobs with a similar title to the searchTerm. Which is what I want, but I suspect that this is a mistake that just coincidentally works the way I want it to.

If I try to achieve my real aim - to return only the applications that have a job with a certain company name - I add the following to the options object using similar logic:

if(x) options.include[0].include[0].where = { name: { [Op.like]: `%${searchTerm}%` } };

... but that returns all the applications, with null for the job and company where the where clause doesn't match

Just to clarify, this isn't what I'm after - I'm trying to get only the applications where the company name is like the searchTerm.

Appreciate any help, let me know if I haven't been clear enough!


So I think I've found the answer: I've been confusing nested where clauses with refering to nested columns from the top-level where clause using the $nested.column$ syntax.

So I can do $nested.nested.column$ and it seems to work:

options.where = {'$job.company.name$': { [Op.like]: ``%${searchTerm}%`` }}

Although I'm still confused as to why my query filtering by a Job column works as expected.

0 Answers
Related