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:
Table | Fields |
---|---|
User | id, name, email |
Product | id, name, price, stock |
Order | id, 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:
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
type Query {
userById(id: ID!): User
users: [User]
userByEmail(email: String!): User
productById(id: ID!): Product
productsByName(name: String!): [Product]
allProducts(sortByPrice: Boolean): [Product]
# ...hingga 33 endpoint query
}
type User {
id: ID
name: String
email: String
orders: [Order]
}
type Product {
id: ID
name: String
price: Float
stock: Int
}
type Order {
id: ID
user: User
product: Product
quantity: Int
createdAt: String
}
Struktur Resolver File & Praktik Baik
Agar maintainable, sebaiknya kita bagi resolver berdasarkan resource/domain:
resolvers/
├─ index.js
├─ userResolver.js
├─ productResolver.js
└─ orderResolver.js
Dan tiap file mempunyai resolusi masing-masing.
Implementasi Resolver dengan Sequelize
Mari langsung ke contoh implementasi. Misal: userResolver.js
// userResolver.js
const { User, Order } = require('../models');
const userResolver = {
Query: {
userById: async (_, { id }) => {
return await User.findByPk(id);
},
users: async () => {
return await User.findAll();
},
userByEmail: async (_, { email }) => {
return await User.findOne({ where: { email } });
}
},
User: {
orders: async (parent) => {
return await Order.findAll({ where: { userId: parent.id } });
}
}
};
module.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
:
const { Product } = require('../models');
const productResolver = {
Query: {
productById: async (_, { id }) => await Product.findByPk(id),
productsByName: async (_, { name }) =>
await Product.findAll({ where: { name } }),
allProducts: async (_, { sortByPrice }) =>
await Product.findAll({
order: sortByPrice ? [['price', 'ASC']] : undefined
}),
// ...Add 30 more as per requirements
}
};
module.exports = productResolver;
Untuk scalability dan DRY (Don’t Repeat Yourself), buat utility untuk automasi beberapa resolver:
function createSimpleFindQuery(model, by) {
return async (_, args) => await model.findOne({ where: { [by]: args[by] } });
}
Simulasi Query: User with Orders
Anggap pengguna ingin data User
beserta daftar Order
:
query {
userById(id: "123") {
id
name
orders {
id
product {
name
price
}
quantity
createdAt
}
}
}
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:
Query | Parameter | Contoh Output |
---|---|---|
userById | id: 123 | {“id”:123, “name”:“Rafi”, “email”:“rafi@foo.com”} |
userByEmail | email: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
- DRY Principle: Jika ada query yang mirip, gunakan helper atau generator.
- Validation: Lakukan validasi parameter sebelum ke DB untuk meminimalisir error dan resiko DB.
- Batching & Caching: Untuk nested resolver, gunakan DataLoader agar mencegah N+1 query problem.
- Error Handling: Gunakan try-catch di setiap resolver dan konsisten error formatnya.
- Documentasi: Tambahkan JSDoc atau komentar minimal endpoint/kegunaan tiap resolver.
- Testing: Siapkan test unit/integrasi khusus untuk setiap resolver.
Benchmark Sederhana
Misal, 33 query dijalankan paralel oleh client. Gunakan Promise.all untuk simultan test:
const allQueries = [
gql1, gql2, /* ... up to gql33 */
];
Promise.all(allQueries.map(q => apolloServer.executeOperation({ query: q })))
.then(results => {
// Evaluasi time taken, error, dsb
});
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 🚀
55. gRPC + Let's Encrypt dengan Autotls
Artikel Terhangat
34 Menyimpan Data ke Database Lewat Mutation
08 Aug 2025
56. Validasi Sertifikat Client di Server
08 Aug 2025
33 Menulis Resolver Query dari Database
08 Aug 2025
55. gRPC + Let's Encrypt dengan Autotls
08 Aug 2025
32 Setup ORM (gorm) di graphql-go
08 Aug 2025
54. Menggunakan Self-signed Certificate
08 Aug 2025
53. Konfigurasi Sertifikat TLS dengan Golang
07 Jul 2025

34 Menyimpan Data ke Database Lewat Mutation

56. Validasi Sertifikat Client di Server

33 Menulis Resolver Query dari Database

55. gRPC + Let's Encrypt dengan Autotls

32 Setup ORM (gorm) di graphql-go

54. Menggunakan Self-signed Certificate
