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 #

TingkatInsertUpdate document yang sudah validUpdate document yang tidak valid
strict (default)diperiksadiperiksadiperiksa
moderatediperiksadiperiksatidak 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:

js
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].options

Output yang Dihasilkan:

text
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:

js
db.produk.insertOne({ nama: "Gula Pasir 1kg", hrga: 15000 })

Output yang Dihasilkan:

text
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:

js
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:

text
{
  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:

  1. Update Teh Melati sukses — document ini memang sudah tidak valid sejak lama (hrga typo), jadi moderate membebaskannya dari pemeriksaan. Ia bahkan boleh tetap tidak valid setelah diedit.
  2. Update harga: "gratis" pada Kopi Gayo ditolak — Kopi Gayo adalah document yang valid, dan moderate melarangnya menjadi tidak valid.
  3. Update stok: 10 pada Kopi Gayo sukses — document valid boleh diedit asal hasilnya tetap valid.

Setelah tim migrasi membereskan seluruh data lama, saatnya menaikkan penjagaan ke tingkat penuh:

js
db.runCommand({ collMod: "produk", validationLevel: "strict" }).ok
db.produk.updateOne({ nama: "Teh Melati 100g" }, { $set: { stok: 8 } })

Output yang Dihasilkan:

text
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:

js
db.dropDatabase()

Output yang Dihasilkan:

text
{ 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.
  • moderate adalah jembatan migrasi: pasang validator lebih awal, bereskan data lama bertahap, lalu naikkan ke strict.
  • collMod bisa mengubah validationLevel sendirian tanpa menyentuh validator yang sudah terpasang.

Kenop terakhir, validationAction, mengubah nasib document yang gagal: ditolak atau diterima dengan catatan — materi Chapter berikutnya.