Validator default bersikap tegas: setiap insert dan setiap update diperiksa, titik. Padahal skenario nyata sering lebih rumit — collection produksi sudah berisi ribuan document lama yang belum bersih, dan memasang validator ketat akan langsung memblokir semua edit atasnya. Untuk situasi itu MongoDB menyediakan opsi validationLevel dengan dua tingkat: strict dan moderate.
Dua Tingkat Pemeriksaan #
| Tingkat | Insert | Update document yang sudah valid | Update document yang tidak valid |
|---|---|---|---|
strict (default) | diperiksa | diperiksa | diperiksa |
moderate | diperiksa | diperiksa | tidak diperiksa |
Tingkat moderate membaca status document sebelum di-update: bila document itu sudah memenuhi validator, hasil editannya wajib tetap valid; bila document itu memang sudah melanggar aturan sejak lama, editnya dibebaskan. Insert baru selalu diperiksa di kedua tingkat. Pola ini dirancang untuk migrasi bertahap: pasang validator saat data lama masih berantakan, biarkan data baru dan data yang sudah bersih terjaga, lalu naikkan ke strict setelah migrasi selesai.
Simulasi Collection Berisi Data Lama #
Kita siapkan produk tanpa validator, lalu isi dengan satu document bersih dan satu document bermasalah — persis seperti collection produksi yang ditumbuhi data lama:
use latihan_validasi
db.produk.drop()
db.createCollection("produk")
db.produk.insertMany([
{ nama: "Kopi Gayo 250g", harga: 85000, kategori: "Minuman" },
{ nama: "Teh Melati 100g", hrga: "mahal" }
])
db.runCommand({ collMod: "produk", validator: { $jsonSchema: {
bsonType: "object",
required: ["nama", "harga"],
properties: {
nama: { bsonType: "string" },
harga: { bsonType: "number", minimum: 0 },
kategori: { enum: ["Minuman", "Makanan", "Alat Tulis"] }
}
} }, validationLevel: "moderate" }).ok
db.getCollectionInfos({ name: "produk" })[0].optionsOutput yang Dihasilkan:
switched to db latihan_validasi
true
{ ok: 1 }
{
acknowledged: true,
insertedIds: {
'0': ObjectId('6ad3912e2f33cf38ba7c7fcb'),
'1': ObjectId('6ad3912e2f33cf38ba7c7fcc')
}
}
1
{
validator: {
'$jsonSchema': {
bsonType: 'object',
required: [ 'nama', 'harga' ],
properties: {
nama: { bsonType: 'string' },
harga: { bsonType: 'number', minimum: 0 },
kategori: { enum: [ 'Minuman', 'Makanan', 'Alat Tulis' ] }
}
}
},
validationLevel: 'moderate',
validationAction: 'error'
}Baris terakhir memastikan opsinya tersimpan: validationLevel: 'moderate' tercatat di metadata collection, sementara validationAction: 'error' tetap menjadi default. Sekarang kita uji ketiga jalur tulis yang berbeda nasibnya:
db.produk.insertOne({ nama: "Gula Pasir 1kg", hrga: 15000 })Output yang Dihasilkan:
Uncaught:
MongoServerError: Document failed validation
Additional information: {
failingDocumentId: ObjectId('6ad3912e2f33cf38ba7c7fcd'),
details: {
operatorName: '$jsonSchema',
schemaRulesNotSatisfied: [
{
operatorName: 'required',
specifiedAs: { required: [ 'nama', 'harga' ] },
missingProperties: [ 'harga' ]
}
]
}
}Insert baru tetap diperiksa ketat walaupun tingkatnya moderate — data baru tidak boleh ikut rusak. Lanjut ke update:
db.produk.updateOne({ nama: "Teh Melati 100g" }, { $set: { stok: 5 } })
db.produk.updateOne({ nama: "Kopi Gayo 250g" }, { $set: { harga: "gratis" } })
db.produk.updateOne({ nama: "Kopi Gayo 250g" }, { $set: { stok: 10 } })
db.produk.find()Output yang Dihasilkan:
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
Uncaught:
MongoServerError: Plan executor error during update :: caused by :: Document failed validation
Additional information: {
failingDocumentId: ObjectId('6ad3912e2f33cf38ba7c7fcb'),
details: {
operatorName: '$jsonSchema',
schemaRulesNotSatisfied: [
{
operatorName: 'properties',
propertiesNotSatisfied: [
{
propertyName: 'harga',
details: [
{
operatorName: 'bsonType',
specifiedAs: { bsonType: 'number' },
reason: 'type did not match',
consideredValue: 'gratis',
consideredType: 'string'
}
]
}
]
}
]
}
}
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
[
{
_id: ObjectId('6ad3912e2f33cf38ba7c7fcb'),
nama: 'Kopi Gayo 250g',
harga: 85000,
kategori: 'Minuman',
stok: 10
},
{
_id: ObjectId('6ad3912e2f33cf38ba7c7fcc'),
nama: 'Teh Melati 100g',
hrga: 'mahal',
stok: 5
}
]Tiga hasil yang berbeda dalam satu blok:
- Update Teh Melati sukses — document ini memang sudah tidak valid sejak lama (
hrgatypo), jadimoderatemembebaskannya dari pemeriksaan. Ia bahkan boleh tetap tidak valid setelah diedit. - Update
harga: "gratis"pada Kopi Gayo ditolak — Kopi Gayo adalah document yang valid, danmoderatemelarangnya menjadi tidak valid. - Update
stok: 10pada Kopi Gayo sukses — document valid boleh diedit asal hasilnya tetap valid.
Setelah tim migrasi membereskan seluruh data lama, saatnya menaikkan penjagaan ke tingkat penuh:
db.runCommand({ collMod: "produk", validationLevel: "strict" }).ok
db.produk.updateOne({ nama: "Teh Melati 100g" }, { $set: { stok: 8 } })Output yang Dihasilkan:
1
Uncaught:
MongoServerError: Plan executor error during update :: caused by :: Document failed validation
Additional information: {
failingDocumentId: ObjectId('6ad3912e2f33cf38ba7c7fcc'),
details: {
operatorName: '$jsonSchema',
schemaRulesNotSatisfied: [
{
operatorName: 'required',
specifiedAs: { required: [ 'nama', 'harga' ] },
missingProperties: [ 'harga' ]
}
]
}
}Dengan strict, edit atas Teh Melati yang belum dibereskan kini ditolak — tidak ada lagi jalur bebas pemeriksaan. Bersihkan database latihan:
db.dropDatabase()Output yang Dihasilkan:
{ ok: 1, dropped: 'latihan_validasi' }Rangkuman #
validationLevel: "strict"(default) memeriksa semua insert dan semua update.validationLevel: "moderate"tetap memeriksa semua insert, tetapi membebaskan update atas document yang memang sudah tidak valid.moderateadalah jembatan migrasi: pasang validator lebih awal, bereskan data lama bertahap, lalu naikkan kestrict.collModbisa mengubahvalidationLevelsendirian tanpa menyentuh validator yang sudah terpasang.
Kenop terakhir, validationAction, mengubah nasib document yang gagal: ditolak atau diterima dengan catatan — materi Chapter berikutnya.