Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
02 Aug 2025 · 5 mnt baca ·Artikel 33 / 125
Go

33 Menulis Resolver Query dari Database

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

33 Menulis Resolver Query dari Database

Di era modern pengembangan aplikasi, arsitektur backend semakin memanjakan kebutuhan klien akan data yang efisien dan fleksibel. Salah satu pendekatan mutakhir adalah menggunakan GraphQL sebagai query language untuk API. Di sisi backend, kita sering dihadapkan dengan kebutuhan untuk menulis resolver agar data di database bisa di-query dengan mudah oleh klien. Tulisan ini akan membedah bagaimana menulis 33 resolver query dari database, dengan pendekatan yang sistematis dan skalabel.

Kita akan melangkah dari konsep dasar, contoh kode, simulasi flow, hingga benchmarking sederhana. Asumsi: Backend menggunakan Node.js dengan Apollo Server dan ORM Sequelize sebagai data layer ke database relasional (PostgreSQL).


Apa Itu Resolver Query?

GraphQL resolver adalah fungsi yang menangani fetching data dari sumber (umumnya database) berdasarkan permintaan query klien. Resolver bisa meng-handle fetch satu baris, banyak baris, filtering, sorting, hingga relasi data.

Setiap field pada GraphQL schema yang butuh data dari database biasanya punya resolvernya sendiri.


Desain Model dan Skema Database

Mari kita bayangkan sebuah database sederhana untuk aplikasi toko online:

TableFields
Userid, name, email
Productid, name, price, stock
Orderid, userId, productId, quantity, createdAt

Anggap saja, ada 33 skenario query yang ingin kita support, seperti:

  • Query user by id
  • Query all users
  • Query user by email
  • Query product by id
  • Query products by name
  • Query all products sorted by price, dst.

Diagram Alur Resolver Query

Untuk memahami prosesnya, berikut flow resolver query dengan kode mermaid:

MERMAID
flowchart TD
    A[Client queries GraphQL] --> B[GraphQL Server menerima query]
    B --> C[Parsing & Validating Query]
    C --> D[Menemukan Resolver]
    D --> E[Resolver Fetch ke DB lewat ORM]
    E --> F[ORM Kirim Data ke Resolver]
    F --> G[Resolver Format Data]
    G --> H[Balas ke Client]

Contoh Skema GraphQL

graphql
 1type Query {
 2  userById(id: ID!): User
 3  users: [User]
 4  userByEmail(email: String!): User
 5  productById(id: ID!): Product
 6  productsByName(name: String!): [Product]
 7  allProducts(sortByPrice: Boolean): [Product]
 8  # ...hingga 33 endpoint query
 9}
10
11type User {
12  id: ID
13  name: String
14  email: String
15  orders: [Order]
16}
17
18type Product {
19  id: ID
20  name: String
21  price: Float
22  stock: Int
23}
24
25type Order {
26  id: ID
27  user: User
28  product: Product
29  quantity: Int
30  createdAt: String
31}

Struktur Resolver File & Praktik Baik

Agar maintainable, sebaiknya kita bagi resolver berdasarkan resource/domain:

text
1resolvers/
2  ├─ index.js
3  ├─ userResolver.js
4  ├─ productResolver.js
5  └─ orderResolver.js

Dan tiap file mempunyai resolusi masing-masing.


Implementasi Resolver dengan Sequelize

Mari langsung ke contoh implementasi. Misal: userResolver.js

js
 1// userResolver.js
 2const { User, Order } = require('../models');
 3
 4const userResolver = {
 5  Query: {
 6    userById: async (_, { id }) => {
 7      return await User.findByPk(id);
 8    },
 9    users: async () => {
10      return await User.findAll();
11    },
12    userByEmail: async (_, { email }) => {
13      return await User.findOne({ where: { email } });
14    }
15  },
16  User: {
17    orders: async (parent) => {
18      return await Order.findAll({ where: { userId: parent.id } });
19    }
20  }
21};
22
23module.exports = userResolver;

Sebagai catatan:

  • Setiap function me-return promise, siap untuk async-await.
  • Penggunaan parent di field resolver untuk menjaga relasi.

Menambah Resolver untuk 33 Query

Untuk mengelola 33 resolver, gunakan pattern generator atau template. Contoh, di productResolver.js:

js
 1const { Product } = require('../models');
 2
 3const productResolver = {
 4  Query: {
 5    productById: async (_, { id }) => await Product.findByPk(id),
 6    productsByName: async (_, { name }) =>
 7      await Product.findAll({ where: { name } }),
 8    allProducts: async (_, { sortByPrice }) =>
 9      await Product.findAll({
10        order: sortByPrice ? [['price', 'ASC']] : undefined
11      }),
12    // ...Add 30 more as per requirements
13  }
14};
15
16module.exports = productResolver;

Untuk scalability dan DRY (Don’t Repeat Yourself), buat utility untuk automasi beberapa resolver:

js
1function createSimpleFindQuery(model, by) {
2  return async (_, args) => await model.findOne({ where: { [by]: args[by] } });
3}

Simulasi Query: User with Orders

Anggap pengguna ingin data User beserta daftar Order:

graphql
 1query {
 2  userById(id: "123") {
 3    id
 4    name
 5    orders {
 6      id
 7      product {
 8        name
 9        price
10      }
11      quantity
12      createdAt
13    }
14  }
15}

Bagaimana resolver menanganinya?

  • Pertama mem-fetch User via ID (userById)
  • Ketika field orders diakses, resolver User.orders di-trigger untuk fetch order
  • Field product dalam Order akan trigger resolver terpisah di tipe Order

Simulasi Output dari 33 Query

Berikut miniatur simulasi output untuk 3 dari 33 query:

QueryParameterContoh Output
userByIdid: 123{“id”:123, “name”:“Rafi”, “email”:“rafi@foo.com ”}
userByEmailemail:foo@bar.com{“id”:99, “name”:“Siti”, “email”:“foo@bar.com ”}
allProducts(sortByPrice: true)sortByPrice: true[{“id”:11,“name”:“T-shirt”,“price”:99.9,…}, …]

Aturan & Tips Menulis Banyak Resolver

  1. DRY Principle: Jika ada query yang mirip, gunakan helper atau generator.
  2. Validation: Lakukan validasi parameter sebelum ke DB untuk meminimalisir error dan resiko DB.
  3. Batching & Caching: Untuk nested resolver, gunakan DataLoader agar mencegah N+1 query problem.
  4. Error Handling: Gunakan try-catch di setiap resolver dan konsisten error formatnya.
  5. Documentasi: Tambahkan JSDoc atau komentar minimal endpoint/kegunaan tiap resolver.
  6. Testing: Siapkan test unit/integrasi khusus untuk setiap resolver.

Benchmark Sederhana

Misal, 33 query dijalankan paralel oleh client. Gunakan Promise.all untuk simultan test:

js
1const allQueries = [
2  gql1, gql2, /* ... up to gql33 */
3];
4
5Promise.all(allQueries.map(q => apolloServer.executeOperation({ query: q })))
6  .then(results => {
7    // Evaluasi time taken, error, dsb
8  });

Penutup

Menulis 33 resolver query memang menantang, terutama untuk menjaga agar kode tetap scalable & maintainable. Fokus pada struktur resolver, automasi untuk query-query yang mirip, dan gunakan best practice GraphQL. Jangan lupa testing dan dokumentasi, agar tim Anda dapat menjaga & mengembangkan codebase secara berkelanjutan.

Kalau ada pengalaman kustom atau tips menulis resolver, boleh sharing di kolom komentar! Happy coding 🚀

Artikel Terkait

💬 Komentar