Пошук з Flask-SQLAlchemy
Будування системи пошуку з базою даних є дуже поширеним завданням. Окрім SQL команд, ми можемо використовувати ORM інструменти, такі як Flask-SQLAlchemy, для створення більш безпечної та організованої системи. Давайте поступово розглянемо, як виконувати пошук, використовуючи синтаксис Flask-SQLAlchemy.
Основний запит
Розпочнемо з простого прикладу: таблиця користувачів з трьома стовпцями — id
, name
та score
.
У Flask-SQLAlchemy ми починаємо запити до бази даних, створюючи об'єкт запиту. Загальний об'єкт запиту можна побудувати, використовуючи session.query()
.
# Запит усіх гравців за допомогою db.session.query()
players = db.session.query(Player).all()
Тут db.session.query(Player)
генерує об'єкт запиту для моделі Player
. Виклик .all()
виконує запит і повертає всі рядки як об'єкти Player
.
Як альтернатива, можна скористатися скороченням, звернувшись безпосередньо до query()
через об'єкт Player
.
# Запит усіх гравців за допомогою Player.query
players = Player.query.all()
Основне фільтрування
Тепер розглянемо ситуацію, коли ви хочете відфільтрувати гравців з високими балами. Це можна зробити за допомогою синтаксису filter
.
players = Player.query.filter(Player.score >= 10).all()
Цей запит поверне тільки Алісу та Чарлі.
Множинні умови
Додамо ще один стовпець, role
, який визначає роль кожного гравця.
Ви можете застосовувати логічні операції and_
та or_
для пошуку з кількома умовами. Припустимо, ви хочете відфільтрувати гравців-воїнів з балами, рівними або більшими за 10. Для цього можна використати оператор and_
:
warrior_players = Player.query.filter(
and_(
Player.level >= 10,
Player.role == 'Warrior'
)
).all()
Цей запит поверне тільки Чарлі.
Пошук без врахування регістру
Пошук за шаблоном особливо корисний при побудові систем, що залежать від пошуку за звичайним текстом. У Flask-SQLAlchemy це можна зробити за допомогою методу ilike
. Наприклад, для пошуку імен користувачів, які починаються на 'a', можна використовувати таку команду:
# Пошук імен гравців, що починаються з "a"
players_starting_with_a = Player.query.filter(Player.name.ilike('a%')).all()
Цей запит поверне тільки користувача Алісу.
А що, якщо ви хочете шукати імена, що містять 'li'?
# Пошук імен гравців, що містять "li"
players_with_li = Player.query.filter(Player.name.ilike('%li%')).all()
У цьому випадку запит поверне як Алісу, так і Чарлі.
Пошук з умовною логікою
Пошук з умовами може бути дуже корисним. Розглянемо ситуацію, коли таблиця player
має три стовпці: id
, player_name
та status
. Стовпець status
відображає поточний стан гравця: 0 для підготовки, 1 для бою і 2 для перемоги.
У базі даних ми можемо використовувати тип INT для збереження значень status
, щоб зекономити пам'ять. Але що, якщо ми хочемо шукати, використовуючи простий текст (наприклад, знайти гравців з status = 0
, шукаючи за 'Preparation')? Як ми можемо це зробити?
У таких випадках корисним стане оператор case
.
Ми можемо відображати цілі числа в текстові описи, використовуючи case
і динамічно будувати необхідні рядки, як показано в наступному прикладі:
Якщо ми шукаємо “battle”:
from sqlalchemy import case, literal, or_
# Пошуковий запит, наданий користувачем
search_term = "battle"
# Запит для пошуку за ім'ям гравця або описом статусу
players_with_status = Player.query.filter(
or_(
Player.name.ilike(f"%{search_term}%"), # Пошук за іменем гравця
case(
(Player.status == 0, literal("Preparation")),
(Player.status == 1, literal("Battle")),
(Player.status == 2, literal("Victory Celebration"))
).ilike(f"%{search_term}%") # Пошук за описом статусу
)
).all()
Оскільки Гравець 1 відповідає опису статусу (‘Battle’), а Гравець 2 відповідає за player_name
, обидва будуть повернуті. Повернуті дані будуть виглядати ось так:
[
(1, "MiagicQQ", "Battle"), # Відповідає опису статусу
(2, "BattleKing1234", "Victory Celebration")# Відповідає імені
]
Перекладено з: [Search Smarter with Flask-SQLAlchemy: Essential Syntax You Need to Know](https://medium.com/@mlshark/search-smarter-with-flask-sqlalchemy-essential-syntax-you-need-to-know-20cbed3c5657)