У сучасній веб-розробці важливо ефективно управляти відносинами між об’єктами в базі даних. Використання ORM (Object-Relational Mapping) спрощує цей процес, дозволяючи розробникам працювати з базою даних, використовуючи високорівневі абстракції. В контексті Swift та серверного фреймворку Vapor, Fluent є потужним інструментом для ORM, який надає широкий спектр можливостей для управління відносинами між моделями. Однак, зіткнувшись з необхідністю виконати складні запити, як-от вибірка даних за певною умовою OR, розробники можуть стикатися з труднощами. Розглянемо, як можна вирішити такі завдання, оптимізувавши роботу з базою даних та забезпечивши високу продуктивність застосунків.
Припустимо, маємо дві моделі: Transaction
та Invoice
. Модель Transaction
містить необов’язкове посилання на Invoice
, що дозволяє зберігати інформацію про транзакції з можливим зв’язком із рахунком-фактурою. Одне з поширених завдань — вибірка транзакцій, де рахунок-фактура або не прив’язаний (nil), або прив’язаний і є активним (властивість isActive
моделі Invoice
істинна). На перший погляд, це завдання може здатися складним для реалізації через обмежені можливості звичайних запитів SQL або через необхідність виконання великої кількості окремих запитів для отримання потрібного результату.
Оптимальним рішенням є застосування LEFT OUTER JOIN
, яке дозволяє об’єднати дані з двох таблиць, повертаючи всі записи з лівої таблиці (Transaction
) навіть тоді, коли умова співпадіння не виконується, тобто не існує відповідного запису в правій таблиці (Invoice
). Додатково можна застосувати фільтрацію до результату об’єднання, щоб відібрати лише ті записи, які відповідають певним критеріям.
1 2 3 4 5 6 7 8 9 10 |
let transactions = (try? await Transaction.query(on: request.db) .with(\.$invoice) .join(Invoice.self, on: \Transaction.$invoice.$id == \Invoice.$id, method: .left) .group(.or) { group in group .filter(Invoice.self, \Invoice.$isActive == true) .filter(\.$invoice.$id == nil) } .sort(\.$dateCreated, .descending) .all()) ?? [] |
У цьому запиті використовується метод join
з параметром .left
для виконання LEFT OUTER JOIN
, який об’єднує таблиці Transaction
та Invoice
. Далі, за допомогою групування за умовою OR
, вибираються транзакції, які або не мають прив’язки до рахунка-фактури, або мають прив’язку до активного рахунка-фактури. Такий підхід дозволяє значно скоротити кількість запитів до бази даних, оптимізуючи загальну продуктивність застосунку.
Використання LEFT OUTER JOIN
у поєднанні з груповими умовами OR
має кілька важливих переваг: