Filter и filter_by в SQLAlchemy: выбор и правильное использование

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

В SQLAlchemy filter поддерживает использование сложных SQL-выражений и стандартные операции сравнения:

Python
Скопировать код
# "Возраст это лишь число... но большее 30" 😆
session.query(MyModel).filter(MyModel.age > 30)

В то же время filter_by применяется для упрощённого использования ключевых аргументов, идеально подходя для проверки равенства:

Python
Скопировать код
# Похоже, Джону сегодня не в духе 🙃
session.query(MyModel).filter_by(age=30)

Используйте filter для выполнения сложных и тонких запросов, а filter_by – для простых и ясных.

Кинга Идем в IT: пошаговый план для смены профессии

Определяем ПРАВИЛЬНЫЙ выбор запроса

filter позволяет вам применять сложные условия с использованием логического ИЛИ, манипулировать SQL-функциями и выполнить сложные операции, недоступные в filter_by:

Python
Скопировать код
# Когда сложно выбрать, кто твой любимый пользователь... Эд или Венди 🤔
from sqlalchemy import or_
session.query(User).filter(or_(User.name == 'ed', User.name == 'wendy'))

filter_by лежит во значении за своим простым и лаконичным синтаксисом для запросов, которые требуют только проверки на равенство и не включают сложных SQL-выражений:

Python
Скопировать код
# Поищем всех тридцатилетних Джонов. Это распространенное имя. 🤷
session.query(MyModel).filter_by(age=30, name='John')

Получаем преимущество с помощью гибкости filter

filter является решением для динамически меняющихся запросов. Он незаменим при построении запросов, основанных на различных условиях:

Python
Скопировать код
# В поисках идеального запроса 🧐
query = session.query(MyModel)
if condition1:
    query = query.filter(MyModel.age > 30)
if condition2:
    query = query.filter(MyModel.name.startswith('A'))
results = query.all()

filter_by не обладает такой гибкостью, поскольку предполагает использование только статически определённых ключевых аргументов.

ЛУЧШЕЕ из двух миров: Объединение filter и filter_by

Мы можем использовать в одном запросе filter и filter_by, объединяя их преимущества:

Python
Скопировать код
# Filter – это левое полушарие, filter_by – правое. Вместе они образуют 'идеальный мозг запроса'!
from sqlalchemy import or_
session.query(MyModel).filter_by(name='John').filter(or_(MyModel.age > 20, MyModel.education == 'PhD'))

Максимально эффективное получение объектов: использование get

Для ускорения работы используйте get для получения объектов по первичному ключу. Он использует карту идентичности сессии и может вернуть объект без выполнения запроса, если он уже присутствует в данной карте:

Python
Скопировать код
# Чемпион по скорости среди ORM? Конечно, '.get()'
my_model = session.query(MyModel).get(primary_key)

Карта идентичности также способствует эффективному использованию кэширования в filter_by, если результаты запросов уже были сохранены в сессии.

Визуализация

Представьте, что вы в библиотеке и ищете книгу по названию:

filter можно сравнить с запросом к библиотекарю найти все книги, в названии которых есть "Advanced". Это предполагает индивидуальный поиск.

📚➡️👓: ["Advanced Cooking", "Advanced Python"] ➡️ Индивидуальный поиск

В то время как filter_by похож на выбор книги на полке, где метка точно соответствует "Advanced Python", обеспечивая прямой и упрощённый поиск.

📚🏷️👓: "Advanced Python" ➡️ Ярлык книги на полке

Основное различие: filter обеспечивает гибкость и сложность, тогда как filter_by обозначает простоту и строгость.

Повышаем уровень с использованием OR в filter

Создание условий с ОР проще с использованием filter. Можно применять побитовый оператор ОР | или функцию or_() из модуля sqlalchemy:

Python
Скопировать код
# Эд или кто-то младше пяти лет. Какова же будет эта компания? 🤣
from sqlalchemy import or_
session.query(User).filter(or_(User.name == 'ed', User.age < 5))

И вариант с побитовым ОР:

Python
Скопировать код
session.query(User).filter((User.name == 'ed') | (User.age < 5))

Битва синтаксисов: filter против filter_by

Разбор синтаксических отличий важен для выбора оптимального способа формулировки запроса:

  • filter: применяется для выражений вида столбец == выражение
Python
Скопировать код
session.query(MyModel).filter(MyModel.age == 30)
  • filter_by: использует ключевые аргументы, равные определенному значению
Python
Скопировать код
# Как бы говоришь: "Алекса, найди модель с возрастом 30 лет". 🗣️🎙️
session.query(MyModel).filter_by(age=30)

Выбирайте синтаксис, который помогает формировать более эффективные и грамотные запросы.

Полезные материалы

  1. Документация SQLAlchemy 2.0 – Здесь вы узнаете больше о методе filter.
  2. Руководство по объектно-реляционному отображению (API 1.x) – Ценный источник информации о работе с Query API в SQLAlchemy 1.4 / 2.0.
  3. GitHub – sqlalchemy/sqlalchemy – Исходный код filter и filter_by.
  4. SQLAlchemy — pysheeet – Удобная шпаргалка по запросам в SQLAlchemy, включая filter, filter_by и другое.
  5. Документация SQLAlchemy 2.0 – Информация о API метода filter_by.