JavaRush /Курси /Модуль 3: Django /Вступ до складних запитів у GraphQL

Вступ до складних запитів у GraphQL

Модуль 3: Django
Рівень 25 , Лекція 0
Відкрита

GraphQL славиться своєю гнучкістю, адже дозволяє запитувати рівно ті дані, які потрібні, і рівно в тому форматі, в якому вони потрібні. Саме тому в реальних додатках ми часто стикаємося з необхідністю обробляти складні запити. Тож, якщо раніше ми будували прості "питаннячка" до API на кшталт "Дай мені список всіх користувачів", то тепер переходимо до створення складних "допитів" виду: "Дай мені список всіх користувачів з їхніми замовленнями, але лише за останній місяць, а ще додай коментарі до замовлень".

Навіщо потрібні складні запити?

Уявіть, що у вас є додаток для інтернет-магазину, і ви хочете отримати дані про певного користувача з його замовленнями, включаючи список товарів у кожному замовленні. У REST API вам довелося б зробити кілька запитів, щоб зібрати всю інформацію. GraphQL дозволяє зробити це за один запит! Це спрощує життя клієнту (менше запитів) і робить API більш зручним для використання.

Приклад запиту:

query {
  user(id: 1) {
    name
    email
    orders {
      id
      total
      items {
        product {
          name
          price
        }
        quantity
      }
    }
  }
}

Цей запит дозволяє вкладено отримати дані про користувача, його замовлення та товари у кожному замовленні. Краса, правда?

Основні концепції складних запитів

Щоб створювати складні запити, потрібно розуміти кілька ключових моментів.

  1. З'єднання даних з декількох моделей

GraphQL легко дозволяє витягувати дані з пов'язаних моделей. Наприклад, ви можете отримати дані з таблиці користувачів, а потім одразу зв'язати її з таблицею замовлень, використовуючи зв'язок ForeignKey у Django. Усе це робиться через GraphQL-схему, без необхідності писати додатковий SQL або вигадувати велосипед.

  1. Обробка великих обсягів даних

У реальних застосунках дані можуть зростати як на дріжджах, і запити, які раніше виконувалися за мілісекунди, починають гальмувати сервер. У таких випадках важливо розуміти, як ефективно формувати складні запити, щоб не перевантажувати сервер і не повертати користувачу зайві дані.

Приклад неефективного запиту:

query {
  users {
    id
    name
    orders {
      id
      items {
        id
      }
    }
  }
}

Якщо у вас 1000 користувачів із тисячами замовлень, сервер «захлинеться» від такого запиту. Ми навчимося, як цього уникнути.

Типи складних запитів

  1. Запити з вкладеннями (Nested Queries)

GraphQL дозволяє запитувати дані, використовуючи вкладені рівні. Наприклад, ви можете запитати статтю та її автора, а також коментарі, написані до цієї статті.

Приклад:

query {
  article(id: 1) {
    title
    content
    author {
      name
      email
    }
    comments {
      text
      user {
        name
      }
    }
  }
}

Цей запит отримує дані не тільки про статтю, але й про її автора, а також про кожен коментар і коментатора.

  1. Запити з фільтрами

Часто в запитах потрібно використовувати фільтри, щоб отримувати тільки ті дані, які відповідають певним умовам. Наприклад, ви можете запитати замовлення, зроблені за минулий тиждень.

Приклад:

query {
  orders(filter: { date_gte: "2023-01-01", date_lte: "2023-01-07" }) {
    id
    total
    user {
      name
    }
  }
}

Ми передали в запит аргумент filter, щоб обмежити вибірку.

Приклади складних запитів

Приклад 1: користувачі з їхніми ролями та правами доступу

Припустимо, у нас є моделі User, Role і Permission. Один користувач може мати кілька ролей, а роль може включати кілька прав.

GraphQL запит:

query {
  users {
    id
    name
    roles {
      name
      permissions {
        name
      }
    }
  }
}

Django модель:

class Permission(models.Model):
    name = models.CharField(max_length=100)

class Role(models.Model):
    name = models.CharField(max_length=100)
    permissions = models.ManyToManyField(Permission)

class User(models.Model):
    name = models.CharField(max_length=100)
    roles = models.ManyToManyField(Role)

Результат:

{
  "data": {
    "users": [
      {
        "id": 1,
        "name": "Alice",
        "roles": [
          {
            "name": "Admin",
            "permissions": [
              { "name": "Can View" },
              { "name": "Can Edit" }
            ]
          }
        ]
      }
    ]
  }
}

Приклад 2: замовлення користувача з товарами

Якщо у нас є користувачі, їхні замовлення та товари в замовленнях, ми можемо написати запит такого виду:

GraphQL запит:

query {
  user(id: 1) {
    name
    orders {
      id
      date
      items {
        product {
          name
          price
        }
        quantity
      }
    }
  }
}

Django модель:

class Product(models.Model):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=10, decimal_places=2)

class OrderItem(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.IntegerField()

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    items = models.ManyToManyField(OrderItem)
    date = models.DateTimeField(auto_now_add=True)

Рекомендації щодо роботи зі складними запитами

  1. Контролюйте вкладеність. Не дозволяйте клієнтам робити запити з нескінченною вкладеністю. Це можна обмежити через налаштування GraphQL двигуна (наприклад, max_depth).

  2. Використовуйте DataLoader для оптимізації. Це допоможе боротися з проблемою N+1 запитів, про яку ми поговоримо в наступних лекціях.

  3. Додавайте фільтри. Обмежте кількість повернених даних, щоб сервер не обробляв мільйони записів.

  4. Використовуйте директиви. GraphQL дозволяє використовувати директиви для управління включенням або виключенням даних.

На цьому етапі у вас мало сформуватися розуміння того, навіщо взагалі потрібні складні запити, як з ними працювати і які основні підходи існують. У наступних лекціях ми заглибимося в реалізацію таких речей, як вкладені запити, вибірки даних, оптимізація і робота з великими обсягами даних.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ