Tips
Type References
Int
Field yang membutuhkan bilangan bulat tanpa bagian desimal (tanpa koma atau titik), baik bernilai positif, negatif, maupun nol.
Seperti: limit, sort, rate, level, count, year, minutes, stock, quantity, total, etc.
Contoh penulisan: 10, -5, 0, 1994
Kapasitas: Berukuran 4 byte dengan rentang nilai dari -2.147.483.648 hingga 2.147.483.647
BigInt
Field yang membutuhkan bilangan bulat berukuran sangat besar, tanpa komponen desimal.
Seperti: monetary amount (pecahan uang), sold, etc.
Contoh penulisan: 9223372036854775807, -100000000000
Kapasitas: Berukuran 8 byte dengan rentang nilai jauh lebih luas, dari -9.223.372.036.854.775.808 hingga 9.223.372.036.854.775.807 (untuk versi signed).
BigInt didukung untuk MongoDB pada Prisma v6. BigInt dipetakan ke tipe MongoDB long. (Prisma) Namun ada batasan penting: nilai yang terlalu besar (melebihi batas 64-bit signed integer) tidak dapat disimpan, karena MongoDB Long memiliki batas tersebut. Jika nilai terlalu besar, disarankan untuk menyimpannya sebagai String.
Float
Field yang membutuhkan angka pecahan atau desimal dengan presisi perkiraan (menggunakan titik . sebagai pemisah desimal).
Seperti: percentage, rating, weight, width, height, length, latitude, longitude, etc.
Contoh penulisan: 3.14, -0.05, 1.23E4 (artinya (1,23 × 10^4))
Karakteristik: Bersifat aproksimasi (mendekati nilai asli), kurang disarankan untuk data keuangan yang menuntut keakuratan mutlak.
Application-level Invariant
Prisma 6 + MongoDB tidak menyediakan Decimal; dokumentasi Prisma 6 secara eksplisit menyatakan Decimal belum didukung pada MongoDB (Prisma).
Gunakan String sebagai pengganti Decimal untuk sementara. baru kemudian melakukan konversi secara manual di aplikasi (misalnya menggunakan library seperti decimal.js) saat membaca atau menulis nilai tersebut.
Karena Prisma + MongoDB tidak memberikan constraint relational sekuat relational SQL, beberapa aturan tidak boleh dianggap sebagai tanggung jawab schema saja.
Contohnya:
OrderItem:
type = product
→ productId atau variantId harus ada
OrderItem:
type = service
→ serviceId harus adaDemikian pula:
PaymentAllocation.amount
<= Payment remaining amount
PaymentAllocation.amount
<= Invoice remaining balancedan:
ShipmentItem.quantity
<= OrderItem.fulfilled-remaining quantityserta:
Refund total
<= Payment totalIni harus dijaga oleh Commerce domain service / transaction logic, bukan mengandalkan Prisma schema.
Units
Perbedaan Int, BigInt, Float, dan Decimal.
| Tipe | Deskripsi | MongoDB | PostgreSQL | Prisma Client JS |
|---|---|---|---|---|
| Int | Integer 32-bit | int | integer | number |
| BigInt | Integer 64-bit | long | bigint | BigInt |
| Float | Bilangan desimal floating-point | double | double precision | number |
| Decimal | Bilangan desimal presisi tinggi | ❌ Tidak didukung | decimal(65,30) | Decimal (Decimal.js) |
Detail:
Int— Untuk bilangan bulat biasa (32-bit). Cocok untuk ID, jumlah, dll.BigInt— Untuk bilangan bulat yang sangat besar (64-bit). Gunakan ini jika nilai bisa melebihi batas Int (~2 miliar). Di Prisma Client, direpresentasikan sebagai tipe JavaScript BigInt. [BigInt reference]Float— Untuk bilangan desimal dengan floating-point. Tidak cocok untuk menyimpan nilai uang karena tidak bisa merepresentasikan desimal secara eksak (bisa terjadi pembulatan). [data modeling]Decimal— Untuk bilangan desimal dengan presisi tinggi (misalnya nilai uang). Di Prisma Client menggunakan library Decimal.js. Namun, Decimal tidak didukung di MongoDB. [Decimal reference] [special fields]
Pilihan terbaik: Jika presisi sangat penting (misalnya nilai keuangan), gunakan String. Jika perlu query langsung di DB dan presisi tidak kritis, gunakan Float.
Perbandingan Pendekatan untuk Nilai Uang di MongoDB
| Pendekatan | Presisi | Batas Nilai | Query DB | Cocok untuk |
|---|---|---|---|---|
| BigInt (satuan terkecil) | ✅ Aman | ⚠️ Maks 64-bit | ✅ Bisa sort/filter | Nilai tidak terlalu besar |
| String + Decimal.js | ✅ Aman | ✅ Tidak terbatas | ❌ Terbatas | Nilai sangat besar / presisi tinggi |
| Float | ⚠️ Berisiko | ✅ Fleksibel | ✅ Bisa sort/filter | Tidak disarankan untuk uang |
Rekomendasi:
- Gunakan BigInt jika nilai uang tidak melebihi batas 64-bit dan Anda butuh kemampuan sorting/filtering di database.
- Jika bekerja dengan nilai crypto seperti wei Ethereum yang sangat besar,
BigIntdi MongoDB tidak cukup — gunakan pendekatanString + Decimal.jssebagai gantinya.
Decimal
Karena Decimal tidak tersedia untuk MongoDB pada Prisma 6, sehingga menyesuaikan beberapa field diganti String atau BigInt.
String
Menangani Nilai Decimal yang Disimpan sebagai String di MongoDB.
Karena Decimal tidak didukung di MongoDB, Anda bisa menggunakan Prisma Client Extensions untuk mengkonversi nilai String ↔ Decimal secara otomatis saat membaca/menulis data.
Pendekatan: Prisma Client Extension (Result Extension)
Konversi dilakukan otomatis saat data dibaca dari database:
import { PrismaClient, Prisma } from '@prisma/client';
const prisma = new PrismaClient().$extends({
result: {
product: {
price: {
needs: { price: true },
compute(product) {
// konversi String → Decimal saat membaca
return new Prisma.Decimal(product.price);
}
}
}
}
});Saat menulis ke database, konversi Decimal → String secara manual:
await prisma.product.create({
data: {
price: new Prisma.Decimal('24.99').toString() // simpan sebagai String
}
});Saat membaca, nilai sudah otomatis menjadi Decimal:
const product = await prisma.product.findFirst();
console.log(product.price); // Prisma.Decimal("24.99")
// bisa langsung pakai operasi Decimal.js
const tax = product.price.times('0.11');
const total = product.price.plus(tax);
console.log(total.toString()); // "27.7389"Keuntungan Pendekatan Ini:
- ✅ Nilai tetap presisi (tidak ada floating-point error)
- ✅ Bisa langsung pakai operasi Decimal.js seperti .plus(), .times(), .minus(), dll.
- ✅ Konversi terpusat, tidak perlu konversi manual di setiap query
Keterbatasan:
- ⚠️ Tidak bisa sorting/filtering berdasarkan nilai numerik langsung di MongoDB (karena tersimpan sebagai String)
- ⚠️ Untuk nested/relational queries, perlu mendefinisikan extension di setiap model yang relevan.
Contoh Operasi Aritmatika dengan Decimal.js:
const product = await prisma.product.findFirst();
// price sudah bertipe Prisma.Decimal
const harga = product.price; // Decimal("24.99")
const diskon = new Prisma.Decimal('0.10');
const hargaAkhir = harga.minus(harga.times(diskon));
console.log(hargaAkhir.toString()); // "22.491"Ini adalah pendekatan paling aman untuk menjaga presisi nilai uang sambil menunggu dukungan resmi Decimal128 di Prisma untuk MongoDB.
Int
BigInt
Menggunakan BigInt untuk Nilai Uang di MongoDB dengan Prisma.
Pendekatan ini umum digunakan di aplikasi web3/crypto (misalnya menyimpan nilai dalam satuan terkecil seperti wei untuk Ethereum), di mana nilai uang direpresentasikan sebagai bilangan bulat tanpa desimal.
Strategi: Simpan dalam Satuan Terkecil. Misalnya, daripada menyimpan Rp 24.500,50, simpan dalam sen/satuan terkecil: 2450050 sebagai BigInt.
model Product {
id String @id @default(auto()) @map("_id") @db.ObjectId
price BigInt // dalam satuan sen/wei/satuan terkecil
}Batasan Penting di MongoDB BigInt di MongoDB dipetakan ke tipe Long (64-bit signed integer), dengan batas:
-9.223.372.036.854.775.808 sampai +9.223.372.036.854.775.807Jika nilai melebihi batas ini (misalnya nilai wei Ethereum seperti 21049200000000000000), akan muncul error:
A number used in the query does not fit into a 64 bit signed integer.Contoh Penggunaan Menulis data:
await prisma.product.create({
data: {
price: BigInt('2450050') // Rp 24.500,50 dalam satuan sen
}
});Membaca dan mengkonversi kembali:
const product = await prisma.product.findFirst();
// konversi kembali ke nilai desimal untuk ditampilkan
const hargaDesimal = Number(product.price) / 100;
console.log(hargaDesimal); // 24500.50Serialisasi ke JSON (perlu penanganan khusus):
JSON.stringify(product, (key, value) => (typeof value === 'bigint' ? value.toString() : value));Ketika menangani invoice/order dengan nilai besar, aggregate, enterprise purchasing, dan sebagainya, batas tersebut terlalu rendah.
Contoh:
unitPrice BigInt
subtotalAmount BigInt
taxAmount BigInt
grandTotalAmount BigIntAda masalah dengan Int dalam menangani monetary amount:
Int32 max ≈ 2.1 billionRepresentasinya adalah minor/smallest monetary unit yang ditetapkan oleh application layer.
Untuk IDR:
Rp150.000
→ 150000nUntuk currency yang memiliki minor unit:
USD 10.50
→ 1050nJangan pernah:
price = 100000.50Dengan demikian kita memperoleh:
- tidak ada floating-point money
- tidak bergantung pada
Decimal - tidak dibatasi Int32
- aman untuk aggregate financial besar
- tetap compatible dengan Prisma 6 + MongoDB
Penggunaan BigInt di Prisma Client:
import { PrismaClient } from '@prisma/client';
const newRecord = await prisma.sample.create({
data: {
revenue: BigInt(534543543534)
}
});Catatan: Jika menggunakan JSON.stringify pada objek yang mengandung BigInt, akan terjadi error. Gunakan serialisasi kustom:
JSON.stringify(this, (key, value) => (typeof value === 'bigint' ? value.toString() : value));
BigInttentu memiliki konsekuensi bahwa serialisasi ke JSON perlu ditangani application layer.
Float
Float dipetakan ke double di MongoDB. Ini lebih mudah untuk query, namun berisiko kehilangan presisi (misalnya 0.1 + 0.2 ≠ 0.3).
⚠️ Prisma sendiri tidak merekomendasikan ini untuk nilai yang membutuhkan presisi tinggi (seperti nilai uang), karena bisa menyebabkan precision errors.
quantity = 1.5
unitPrice = 100000nKarena commerce tidak selalu menjual hanya unit integer.
Misal:
1.5 kg
2.5 meter
0.75 hour
1.25 literJika bisnis tertentu hanya mengizinkan integer quantity, application/domain validation dapat menetapkan:
quantity % 1 === 0"Mengakali" Penggunaan Decimal di MongoDB dengan Prisma v6 Karena Decimal tidak didukung secara native di MongoDB pada Prisma, berikut beberapa pendekatan yang disebutkan dalam knowledge sources:
- Gunakan String sebagai pengganti Decimal (Rekomendasi Resmi) Prisma secara resmi menyarankan penggunaan String sebagai alternatif sementara:
model Product {
id String @id @default(auto()) @map("_id") @db.ObjectId
price String // simpan nilai desimal sebagai string
}Kekurangan: tidak bisa melakukan filtering/sorting/aggregasi langsung di database.
Tabel Rekomendasi Tipe Field Prisma
⚠️ Tabel ini dibuat berdasarkan knowledge sources yang tersedia. Beberapa rekomendasi (terutama untuk latitude, longitude, weight, height, length) tidak disebutkan secara eksplisit dalam knowledge sources — saya akan menandainya dengan asumsi berdasarkan karakteristik tipe data.
Nilai Uang (Money / Price)
| Database | Tipe Prisma | Alasan |
|---|---|---|
| PostgreSQL | Decimal (@db.Money atau @db.Decimal(p,s)) | Presisi tinggi, tidak ada floating-point error [Decimal reference] |
| MySQL | Decimal (@db.Decimal(p,s)) | Sama seperti PostgreSQL, presisi terjamin [Decimal reference] |
| MongoDB | String + Decimal.js atau BigInt (satuan terkecil) | Decimal tidak didukung MongoDB [MongoDB mapping] |
| SQLite | Decimal | Dipetakan ke DECIMAL [Decimal reference] |
Weight / Height / Length (Berat, Tinggi, Panjang)
⚠️ Tidak disebutkan secara eksplisit dalam knowledge sources. Rekomendasi berikut berdasarkan karakteristik tipe data Prisma.
| Database | Tipe Prisma | Alasan |
|---|---|---|
| PostgreSQL | Decimal (@db.Decimal(p,s)) | Presisi tinggi untuk nilai fisik (misal: 72.500 kg) [Decimal reference] |
| MySQL | Decimal (@db.Decimal(p,s)) | Sama seperti PostgreSQL [Decimal reference] |
| MongoDB | Float (jika presisi tidak kritis) atau String + Decimal.js | Decimal tidak didukung [MongoDB mapping] |
| SQLite | Decimal | Dipetakan ke DECIMAL [Decimal reference] |
Count / Quantity / Order (Jumlah, Kuantitas)
| Database | Tipe Prisma | Alasan |
|---|---|---|
| PostgreSQL | Int | Jumlah barang tidak perlu desimal, 32-bit cukup untuk kebanyakan kasus [Int reference] |
| MySQL | Int | Sama seperti PostgreSQL [Int reference] |
| MongoDB | Int | Dipetakan ke int MongoDB [MongoDB mapping] |
| SQLite | Int | Dipetakan ke INTEGER [Int reference] |
Jika jumlah bisa sangat besar (misal total transaksi global), gunakan BigInt.
Sort / Urutan (Sort Order)
| Database | Tipe Prisma | Alasan |
|---|---|---|
| PostgreSQL | Int | Nilai urutan biasanya bilangan bulat kecil [Int reference] |
| MySQL | Int | Sama seperti PostgreSQL [Int reference] |
| MongoDB | Int | Dipetakan ke int MongoDB [MongoDB mapping] |
| SQLite | Int | Dipetakan ke INTEGER [Int reference] |
Latitude / Longitude (Koordinat GPS)
⚠️ Tidak disebutkan secara eksplisit dalam knowledge sources. Rekomendasi berikut berdasarkan karakteristik tipe data Prisma.
| Database | Tipe Prisma | Alasan |
|---|---|---|
| PostgreSQL | Float (@db.DoublePrecision) | Koordinat GPS butuh ~15 digit presisi, double precision cukup. Tipe point belum didukung Prisma [PostgreSQL mapping] |
| MySQL | Float | Dipetakan ke DOUBLE |
| MongoDB | Float | Dipetakan ke double MongoDB [MongoDB mapping] |
| SQLite | Float | Dipetakan ke REAL |
Year (Tahun)
| Database | Tipe Prisma | Alasan |
|---|---|---|
| PostgreSQL | Int atau DateTime | Int jika hanya butuh tahun saja; DateTime jika butuh perbandingan/sorting waktu [PostgreSQL mapping] |
| MySQL | Int (@db.Year) | MySQL punya tipe native YEAR yang dipetakan ke Int [Int reference] |
| MongoDB | Int | Tidak ada tipe YEAR native, Int paling sesuai [MongoDB mapping] |
| SQLite | Int | Dipetakan ke INTEGER [Int reference] |
Ringkasan
| Use Case | PostgreSQL | MySQL | MongoDB | SQLite |
|---|---|---|---|---|
| Nilai uang | Decimal | Decimal | String/BigInt | Decimal |
| Berat/Tinggi/Panjang | Decimal | Decimal | Float/String | Decimal |
| Count/Quantity | Int | Int | Int | Int |
| Sort order | Int | Int | Int | Int |
| Latitude/Longitude | Float | Float | Float | Float |
| Tahun | Int/DateTime | Int (@db.Year) | Int | Int |