Перейти до основного вмісту

Схема GraphQL

SubQuery TeamПриблизно 4 хв

Схема GraphQL

Визначення об'єктів

Файл schema.graphql визначає різні схеми GraphQL. Відповідно до того, як працює мова запитів GraphQL, файл схема, по суті, диктує форму ваших даних від SubQuery. Щоб дізнатися більше про те, як писати в мові GraphQL, ми рекомендуємо переглянути схему і типиopen in new window.

Важливо: після внесення будь-яких змін до файлу схеми, будь ласка, переконайтеся, що ви регенеруєте каталог типів за допомогою наступної команди yarn codegen

Об'єкти

Кожний об'єкт повинен визначити свої обов'язкові поля id з типом ID!. Він використовується як первинний ключ і унікальний серед всіх об'єктів одного типу.

Недопустимі поля в об'єкті !. Будь ласка, перегляньте наведений нижче приклад:

type Example @entity {
  id: ID! # id field is always required and must look like this
  name: String! # This is a required field
  address: String # This is an optional field
}

Підтримувані скаляри та типи

На даний момент ми підтримуємо типи скалярних елементів:

  • ID
  • Int
  • Рядок
  • BigInt
  • Плаваючий
  • Дата
  • Логічний тип
  • <EntityName> для вкладених відношень, ви можете використовувати ім'я визначеного об'єкту як один із полів. Будь ласка, побачити в зв'язок істот.
  • JSON може альтернативно зберігати структуровані дані, будь ласка, перегляньте тип JSON
  • <EnumName> типи є спеціальним видом перерахованого скаляру, який обмежується конкретним набором допустимих значень. Будь ласка, погляньте Graphql Enumopen in new window

Індексування по полю не основного ключа

Для поліпшення продуктивності запитів, індексувати поле об'єкта просто шляхом впровадження анотації @index в поле без основного ключа.

Проте, ми не дозволяємо користувачам додавати @індекс анотації на будь-якому об'єкті JSON. За замовчуванням індекси автоматично додаються до зовнішніх ключів та до полів JSON в базі даних, але лише для покращення продуктивності сервісу запитів.

Ось приклад:

type Example @entity {
  id: ID!
  назва: Рядок! @index(унікальний: істина) # унікальний може бути встановлений значення true або false
  title: Назва! # Індекси автоматично додаються до зовнішнього ключового поля
}

тип Title @entity {
  id: ID!
  назва: Рядок! @index(unique:true)
}

Припускаючи, що ми знали ім'я користувача, але ми не знаємо точної ідентифікаційної цінності, замість того, щоб вилучати всіх користувачів, а потім фільтрувати за назвою, яку ми можемо додати @index за полем. Цей процес робить запит набагато швидшим і додатково ми можемо передати унікальність: true для удосконалення унікальності.

Якщо поле не є унікальним, максимальний розмір цього результату 100

Коли запущено генерацію коду, це автоматично створить getByName під моделлю користувача, і поле стороннього ключа, заголовок створить метод getByTitleId до якого можна отримати безпосередній доступ в функції.мап.

/* Підготувати запис для об'єкта title */
INSERT INTO (id, ім'я) VALUES ('id_1', 'Капітан')
// Handler in mapping function
import { User } from "../types/models/User";
import { Title } from "../types/models/Title";

const jack = await User.getByName("Jack Sparrow");

const captainTitle = await Title.getByName("Captain");

const pirateLords = await User.getByTitleId(captainTitle.id); // List of all Captains

Зв'язки об'єктів

В сутності часто є вкладені стосунки з іншими суб'єктами. Встановлення значення поля в іншу назву сутності визначає типовий зв'язок між цими двома сутностями.

Маси відповідності сутності (один до одного і багато-багатьох) можна налаштувати на прикладах нижче.

Багато в одному відношенні

Одне до одного відношення є типовим, коли лише один об'єкт накладається на інший об'єкт.

Приклад: паспорт належить лише одній особі і має лише один паспорт (у цьому прикладі):

type Example @entity {
  id: ID!
}
type Example @entity {
  id: ID!
  owner: Person!
}

або

type Example @entity {
  id: ID!
  passport: Passport!
}
type Example @entity {
  id: ID!
}

стосунків багато-багато

Ви можете використовувати квадратні дужки, щоб вказати, що тип поля включає декілька сутностей.

Приклад: людина може мати кілька облікових записів.

type Example @entity {
  id: ID!
  accounts: [Account]! @derivedFrom(field: "person") #This is virtual field
}

type Account @entity {
  id: ID!
  person: Person!
}

стосунків багато-багато

Взаємовідносини багато-багато можна досягти, реалізуючи суб'єкт картографування для з'єднання двох інших об'єктів.

Приклад: Кожна людина є частиною декількох груп (PersonGroup), а групи мають безліч різних людей (PersonGroup).

type Example @entity {
  id: ID!
  name: String!
}

type PersonGroup @entity {
  id: ID!
  person: Person!
  Group: Group!
}

type Group @entity {
  id: ID!
  name: String!
}

Також можна створити з'єднання одного і того ж об'єкта в декількох полях середнього об'єкта.

Наприклад, обліковий запис може мати кілька переказів, і кожен переказ має джерело та обліковий запис призначення.

Це встановить двонаправлений зв’язок між двома Рахунками (від та до) через таблицю передачі.

type Account @entity {
  id: ID!
  publicAddress: String!
}

type Transfer @entity {
  id: ID!
  amount: BigInt
  from: Account!
  to: Account!
}

Зворотні пошуки

Щоб увімкнути зворотний пошук сутності до відношення, приєднайте @ похідне від до поля та вкажіть на його зворотне поле пошуку іншого об'єкта.

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

Переказ "з" облікового запису доступний від суб'єкта рахунку, встановивши надісланий Передавач або отриманий Передача як такий, що має їх значення, отримане з відповідних полів або з них.

type Account @entity {
  id: ID!
  publicAddress: String!
  sentTransfers: [Transfer] @derivedFrom(field: "from")
  receivedTransfers: [Transfer] @derivedFrom(field: "to")
}

type Transfer @entity {
  id: ID!
  amount: BigInt
  from: Account!
  to: Account!
}

Тип JSON

Ми підтримуємо збереження даних як тип JSON, що є швидким способом зберігання структурованих даних. Ми автоматично створимо відповідні інтерфейси JSON для запиту цих даних і заощадимо час на визначення та управління об'єктами.

Ми рекомендуємо користувачам використовувати тип JSON у таких сценаріях:

  • Зберігання структурованих даних в одному полі є більш керованим, ніж створення декількох окремих об'єктів.
  • Збереження довільних налаштувань користувача ключа / значення (де значення може бути булевим, текстовим або числовим, і ви не хочете мати окремі стовпці для різних типів даних)
  • Схема мінлива і часто змінюється

Визначте директиву JSON

Визначте властивість як тип JSON, додавши в суб'єкт господарювання jsonField. Це автоматично генерує інтерфейси для всіх об'єктів JSON у вашому проекті під types / interfaces.ts, і ви можете отримати доступ до них у своїй функції картографування.

На відміну від сутності, об'єкт директиви jsonField не вимагає поля id. Об'єкт JSON також здатний гніздитися з іншими об'єктами JSON.

type AddressDetail @jsonField {
  street: String!
  district: String!
}

type ContactCard @jsonField {
  phone: String!
  address: AddressDetail # Nested JSON
}

type User @entity {
  id: ID!
  contact: [ContactCard] # Store a list of JSON objects
}

Запит полів JSON

Недолік використання типів JSON незначний вплив на ефективність запиту при фільтруванні, оскільки кожен раз, коли він здійснює пошук тексту, він відбувається на всій сутності.

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

#Щоб знайти перші 5 користувачів власних телефонних номерів містить '0064'.

query {
  user(first: 5, filter: { contactCard: { contains: [{ phone: "0064" }] } }) {
    nodes {
      id
      contactCard
    }
  }
}