Reputation: 127
I'm implementing some search functionality for a database of companies and their subsidiaries. For each company there may be multiple subsidiaries or none. Each subsidiary has a company_id column that links it to the id column of the parent company table.
Here is an example of how searching for a company by name:
def search_by_company_name(name):
company_search = session.query(Company.name).filter(Company.name.like('%{}%'.format(name)))
return company_search.all()
What I want is to be able to query a company by searching for not only its name but also the names of any subsidiaries that might share a similar name. What I have right now is:
def search_by_company_and_subsidiary_name(name):
company_search = session.query(Company.name).filter(Company.name.like('%{}%'.format(name)) | Subsidiary.name.like('%{}%'.format(name)))
search_results = company_search.filter(Company.id == Subsidiary.company_id)
return search_results.all()
The problem with my approach is that if there are no subsidiaries for a certain parent company, then the query returns nothing, even if the name search matches to a row in the Company table.
For example:
search_by_company_name('accenture')
>>> [('Accenture',)]
However
search_by_company_and_subsidiary_name('accenture')
>>> []
I'm sure that the second function is returning [] because there are no subsidiaries for Accenture in my database, so the predicate .filter(Subsidiary.company_id == Company.id)
is essentially removing any results already found in the Company table. I'm thinking the solution might be to do something like a left join, but I haven't had any luck after troubleshooting for a while.
Is there a good way to do a query like this in SQLAlchemy that will still return all the rows found in a certain table when there are no matching rows in the Subsidiary table for a given company?
Upvotes: 2
Views: 1100
Reputation: 2173
You might consider implementing an outerjoin rather than a strict filter condition, e.g. something along the lines of:
def search_by_company_and_subsidiary_name(name):
return session.query(Company)
.outerjoin(Subsidiary, Company.id == Subsidiary.company_id)
.filter(Company.name.like('%{}%'.format(name)) | Subsidiary.name.like('%{}%'.format(name)))
.all()
Upvotes: 3