Validator bermula dari pertanyaan paling mendasar: field mana yang wajib ada di setiap document? Kata kunci required menjawabnya dengan daftar nama field. Sederhana sekali kelihatannya — tetapi ada satu jebakan null yang membuat banyak orang kaget: required memeriksa kehadiran field, bukan tipe isinya. Chapter ini membedah keduanya.
Daftar Field Wajib #
Kita definisikan produk dengan tiga field wajib — nama, sku, harga — sementara kategori, stok, deskripsi, dan tanggal_ditambahkan boleh absen:
use latihan_validasi
db.produk.drop()
db.createCollection("produk", { validator: { $jsonSchema: {
bsonType: "object",
required: ["nama", "sku", "harga"],
properties: {
nama: { bsonType: "string", minLength: 3 },
sku: { bsonType: "string", pattern: "^[A-Z]{3}-[0-9]{3}$" },
harga: { bsonType: "number", minimum: 0 },
kategori: { enum: ["Minuman", "Makanan", "Alat Tulis"] },
stok: { bsonType: "int", minimum: 0 },
deskripsi: { bsonType: ["string", "null"] },
tanggal_ditambahkan: { bsonType: "date" }
}
} } })
db.produk.insertOne({ nama: "Kopi Gayo 250g", sku: "MIN-001", harga: 85000, kategori: "Minuman", stok: 40, tanggal_ditambahkan: new Date("2026-01-10") })
db.produk.insertOne({ nama: "Teh Melati 100g", sku: "MIN-002", harga: 12000 })
db.produk.find()Output yang Dihasilkan:
switched to db latihan_validasi
true
{ ok: 1 }
{
acknowledged: true,
insertedId: ObjectId('6ad39063519a8f4168bb439b')
}
{
acknowledged: true,
insertedId: ObjectId('6ad39063519a8f4168bb439c')
}
[
{
_id: ObjectId('6ad39063519a8f4168bb439b'),
nama: 'Kopi Gayo 250g',
sku: 'MIN-001',
harga: 85000,
kategori: 'Minuman',
stok: 40,
tanggal_ditambahkan: ISODate('2026-01-10T00:00:00.000Z')
},
{
_id: ObjectId('6ad39063519a8f4168bb439c'),
nama: 'Teh Melati 100g',
sku: 'MIN-002',
harga: 12000
}
]Document pertama lengkap, document kedua hanya berisi field wajib — keduanya lolos. Inilah pola wajib + opsional: field yang masuk daftar required wajib hadir, field yang hanya disebut di properties dijaga tipenya bila ada. Perhatikan juga kedua document punya _id otomatis: _id selalu dibuat server dan tidak pernah perlu dimasukkan ke required.
Menyisihkan satu field wajib langsung terlihat oleh server. Coba kirim produk tanpa sku:
db.produk.insertOne({ nama: "Gula Pasir 1kg", harga: 15000 })Output yang Dihasilkan:
Uncaught:
MongoServerError: Document failed validation
Additional information: {
failingDocumentId: ObjectId('6ad39063519a8f4168bb439d'),
details: {
operatorName: '$jsonSchema',
schemaRulesNotSatisfied: [
{
operatorName: 'required',
specifiedAs: { required: [ 'nama', 'sku', 'harga' ] },
missingProperties: [ 'sku' ]
}
]
}
}Galatnya berbeda dari semua yang kita lihat sejauh ini: operatorName: 'required' dengan missingProperties: [ 'sku' ] — nama field yang absen disebut satu per satu.
Jebakan: required Tanpa bsonType Melewatkan null #
Sekarang jebakannya. required hanya bertanya “apakah fieldnya ada?” — dan field bernilai null dianggap ada. Kita buat collection kedua yang hanya memakai required tanpa properties sama sekali:
db.produk2.drop()
db.createCollection("produk2", { validator: { $jsonSchema: {
bsonType: "object",
required: ["nama", "harga"]
} } })
db.produk2.insertOne({ nama: null, harga: null })
db.produk2.find()Output yang Dihasilkan:
true
{ ok: 1 }
{
acknowledged: true,
insertedId: ObjectId('6ad39063519a8f4168bb439e')
}
[
{ _id: ObjectId('6ad39063519a8f4168bb439e'), nama: null, harga: null }
]Insert lolos, dan hasil find() memperlihatkan document dengan kedua field wajib bernilai null. Bagi required, dokumen { nama: null, harga: null } memenuhi kontrak: fieldnya hadir semua.
Kita perbaiki produk2 dengan menambahkan properties lewat collMod, lalu kirim document yang sama:
db.runCommand({ collMod: "produk2", validator: { $jsonSchema: {
bsonType: "object",
required: ["nama", "harga"],
properties: {
nama: { bsonType: "string" },
harga: { bsonType: "number", minimum: 0 }
}
} } }).ok
db.produk2.insertOne({ nama: null, harga: null })Output yang Dihasilkan:
1
Uncaught:
MongoServerError: Document failed validation
Additional information: {
failingDocumentId: ObjectId('6ad39063519a8f4168bb439f'),
details: {
operatorName: '$jsonSchema',
schemaRulesNotSatisfied: [
{
operatorName: 'properties',
propertiesNotSatisfied: [
{
propertyName: 'nama',
details: [
{
operatorName: 'bsonType',
specifiedAs: { bsonType: 'string' },
reason: 'type did not match',
consideredValue: null,
consideredType: 'null'
}
]
},
{
propertyName: 'harga',
details: [
{
operatorName: 'bsonType',
specifiedAs: { bsonType: 'number' },
reason: 'type did not match',
consideredValue: null,
consideredType: 'null'
}
]
}
]
}
]
}
}Kali ini ditolak. Bagian required lolos (kedua field ada), tetapi properties menemukan dua pelanggaran bsonType sekaligus: nama bernilai null padahal menuntut string, dan harga bernilai null padahal menuntut number. Gabungan required + bsonType barulah kontrak yang utuh.
Bersihkan database latihan:
db.dropDatabase()Output yang Dihasilkan:
{ ok: 1, dropped: 'latihan_validasi' }Rangkuman #
required: ["nama", "sku", "harga"]mewajibkan kehadiran field — bukan tipe atau isinya.- Field opsional cukup disebut di
properties; aturannya berlaku hanya saat field tersebut ada. _iddibuat otomatis oleh server dan tidak pernah perlu masuk daftarrequired.- Jebakan null: field bernilai
nulldianggap hadir, jadirequiredtanpabsonTypemembiarkannya lolos. - Pasangan
required+propertiesdenganbsonTypemembentuk kontrak lengkap: hadir dan bertipe benar.
Selanjutnya kita naik satu tingkat: menggabungkan banyak aturan dalam satu validator, memvalidasi isi array, dan menutup field yang tidak dikenal.