Python Friday #82: Filters in SQLAlchemy ORM

When we access our database, we most often only want to work with a few specific rows and not the whole table. Let us look what syntax SQLAlchemy ORM uses to filter our rows.

This post is part of my journey to learn Python. You can find the other parts of this series here. You find the code for this post in my PythonFriday repository on GitHub.

 

Pre-requisites

To follow along, please make sure that you have SQLAlchemy installed and that you have the Northwind database for SQLite next to your Python script. We need all the code from Creating the Foundation for SQLAlchemy ORM to work with the Employee table.

 

Overview on the filters in SQLAlchemy ORM

Here is an overview of the filters you can use with SQLAlchemy ORM:

Filter Syntax
ALL session.query(Employee)
EQUALS session.query(Employee).filter(Employee.id == 1)
NOT EQUALS session.query(Employee).filter(Employee.id != 1)
GREATER THAN session.query(Employee).filter(Employee.id > 5)
LESS THAN session.query(Employee).filter(Employee.id < 5)
LIKE session.query(Employee).filter(Employee.last_name.like(“Pe%k”))
session.query(Employee).filter(Employee.last_name.contains(“u”))
session.query(Employee).filter(Employee.last_name.startswith(“D”))
session.query(Employee).filter(Employee.last_name.endswith(“n”))
NOT LIKE session.query(Employee).filter(Employee.last_name.not_like(“Pe%k”))
IN session.query(Employee).filter(Employee.id.in_([1,2,3]))
NOT IN session.query(Employee).filter(Employee.id.not_in([1,2,3]))
session.query(Employee).filter(~Employee.id.in_([1,2,3]))
AND session.query(Employee).filter(filterA, filterB)
session.query(Employee).filter(and_(filterA, filterB))
session.query(Employee).filter(filterA).filter(filterB))
OR session.query(Employee).filter(or_(filterA, filterB))

 

Select all rows

If we do not specify any filters, our query will get us all rows in a database table:

 

Equals / not equals

We can filter the rows for a column that is equal to a specific value with the same == operator as we use in other parts of Python:

If we want the opposite, we can use the != operator (not equals):

 

Greater than / less than

If we want numerical values that are greater than (>)a specific value, we can use this code:

For smaller values we can use < instead:

The same works with greater or equals (>=) and less or equals (<=).

 

Like / not like

If we want to match part of a string, we can use the like() method and use % as a placeholder:

The opposite effect has the not_like() method:

 

Contains, startswith and endswith

There are 3 methods for a bit more convenience that let us focus on the place in which we want to match a string. They translate to LIKE in SQL, but we do not need to set the % placeholder. If the string we search for can be anywhere, we use the contains() method:

If the string we search is at the beginning, we use the startswith() method:

For strings that end in a certain way we can use the endswith() method:

 

In / not in

We can filter rows where a value is in a list with the in_() method:

The word in is a reserved keyword in Python. Therefore, SQLAlchemy cannot use it for its own method and adds a _ at the end.

For the opposite of in_ we can use the not_in() method:

Sometimes you find code examples that use a ~ operator (bitwise NOT) that you can use to negate the in_() method:

 

Combine filters with AND

The power of SQL comes with combining multiple filters in the same query. If we want multiple filters to be true at the same time, we can create an AND in SQL by adding multiple filters separated by a comma (,):

The same effect has the and_() method (the _ is necessary because and is also a reserved keyword in Python):

To complete the list of possible ways to combine filters with AND, you can add multiple .filter() clauses:

In SQLAlchemy Core we used the & operator, but this one does not work in ORM and throws an exception:

TypeError: unsupported operand type(s) for &: ‘int’ and ‘InstrumentedAttribute’

 

Combine filters with OR

If we want multiple filters where at least one is true, we can create an OR in SQL with the or_() method:

The Python | operator works in SQLAlchemy Core, but throws an exception in the ORM part:

TypeError: unsupported operand type(s) for |: ‘int’ and ‘InstrumentedAttribute’

 

Next

Filters use a different syntax in the ORM as they do in Core. Nevertheless, you can nearly reuse all concepts and get just the data that you need. Next week we have a closer look on how the relationship patterns work in SQLAlchemy ORM.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.