Keçən dərsdə məlumat massivlərdə idi və server yenidən başladıqda itirdi. İndi həqiqi bazanı — Prisma vasitəsilə PostgreSQL-i — qoşacağıq və eyni zamanda GraphQL-in resolver-ləri necə çağırdığını anlayacağıq. Konveyeri təsəvvür edin: hər məntəqədə işçi əvvəlki məntəqədən detal alır. Birincisi postların siyahısını yığır, növbətilər hər postu tamamlayır — müəllif, şərhlər əlavə edir. Əvvəlki məntəqənin ötürdüyü şey elə parent-dir.

Resolver-in imzası

İstənilən resolver (parent, args, contextValue, info) funksiyasıdır:

ParametrBu nədir
parentvalideyn sahənin resolver-inin qaytardığı (Post.author-da — postun obyekti)
argssorğudakı sahə arqumentləri (user(id: "1") üçün { id: '1' })
contextValuecontext funksiyasından gələn sorğunun ümumi obyekti (məsələn, { prisma })
infoxidməti məlumat: sahənin adı, yol, sxem; nadir hallarda lazımdır

Resolver dəyər, null və ya Promise qaytarır. Obyekt və ya obyektlər massivi qaytarılıbsa, Apollo onların daxili sahələrinin resolver-lərini işə salır — ən sadə dəyərlərə qədər belə davam edir.

Resolver ağacı

Sorğu ağac kimi icra olunur. { posts { title author { name } } } sorğusuna baxaq:

Resolver ağacı: Query.posts, sonra hər post üçün Post.title və Post.author, sonra User.name
Resolver ağacı: Query.posts, sonra hər post üçün Post.title və Post.author, sonra User.name
  • Query.posts bir dəfə çağırılır və postların siyahısını qaytarır.
  • Hər post üçün Post.title və Post.author çağırılır: 10 post olsa, Post.author 10 dəfə işləyəcək — bunu N+1 dərsi üçün yadda saxlayın.
  • Hər müəllif üçün User.name çağırılır; onun parent-i Post.author-un qaytardığı istifadəçidir.
  • Uşaq resolver valideyni gözləyir, eyni səviyyənin sahələrini isə Apollo bir-birindən asılı olmadan işə salır.

Susmaya görə resolver-lər

Hər sahə üçün resolver lazım deyil. Resolver yoxdursa, GraphQL parent-dən sahə adı ilə xassəni götürür, funksiyadırsa — onu çağırır. Ona görə Post.title, Post.body və User.name özü işləyir: belə xassələr bazadan gələn sətirdə artıq var. Post.id rəqəmini "1" sətrinə ID skalyarı özü çevirir. Öz resolver-i üç halda yazırlar:

  • kök sahələr (Query.*): onların valideyni yoxdur, məlumatı bazadan götürürük;
  • əlaqələr (Post.author, User.posts, Post.comments): sətirdə yalnız authorId var və ya heç nə yoxdur;
  • fərqli formatlı sahələr (Post.createdAt): bazada Date, sxemdə isə String.
GraphQL sxemi və verilənlər bazası: hansı sahələr özü işləyir, hansılara resolver lazımdır
GraphQL sxemi və verilənlər bazası: hansı sahələr özü işləyir, hansılara resolver lazımdır

Context-də Prisma

Prisma ORM 7-ni verilənlər bazaları bölməsində qurmusunuz. Eyni PostgreSQL konteynerində yeni blog_graphql bazası yaradın və Prisma-nı inisializasiya edin:

bash
npm install @prisma/client@7 @prisma/adapter-pg@7 pg
npm install -D prisma@7 dotenv
npx prisma init --datasource-provider postgresql --output ../src/generated/prisma --no-skills

prisma/schema.prisma-da modelləri təsvir edin — GraphQL sxemi ilə eyni varlıqlar (@map atributları qısalıq üçün buraxılıb), — sonra npx prisma migrate dev --name init və npx prisma generate əmrlərini icra edin:

prisma
model User {
  id       Int       @id @default(autoincrement())
  name     String
  email    String    @unique
  posts    Post[]
  comments Comment[]
}