11-bo‘lim

Sxema tekshiruvi

$jsonSchema bilan qoida yozish, majburiy maydonlar va turlar, validationLevel va validationAction, mavjud to'plamga qoida qo'shish.

🕑 16 daqiqa o‘qish 📄 891 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Nima uchun kerak
  2. Qoida ishlayaptimi
  3. Asosiy kalit so'zlar
  4. validationLevel va validationAction
  5. Mavjud to'plamga qoida qo'shish
  6. Qoidani ko'rish va olib tashlash
  7. Qoida qayerda bo'lishi kerak
  8. Xulosa

MongoDB sxemani talab qilmaydi - lekin siz uni talab qilishingiz mumkin. Bu ikki dunyoning eng yaxshi tomonini birlashtiradi: moslashuvchanlik kerak joyda qoladi, qat'iylik esa kerak joyda qo'yiladi.

JavaScript
db.createCollection("xodim", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["ism", "lavozim", "maosh"],
      properties: {
        ism: {
          bsonType: "string",
          minLength: 2,
          description: "ism kamida 2 belgidan iborat matn bo'lsin"
        },
        lavozim: {
          enum: ["dasturchi", "tahlilchi", "menejer"],
          description: "lavozim ro'yxatdagi qiymatlardan biri bo'lsin"
        },
        maosh: {
          bsonType: "int",
          minimum: 1000000,
          description: "maosh butun son va 1 000 000 dan katta bo'lsin"
        },
        email: {
          bsonType: "string",
          pattern: "^.+@.+$",
          description: "email da @ belgisi bo'lishi kerak"
        }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
})

db.xodim.insertMany([
  { _id: 1, ism: "Husanboy", lavozim: "dasturchi", maosh: Int32(9000000) },
  { _id: 2, ism: "Malika",   lavozim: "tahlilchi", maosh: Int32(7500000) }
])

Nima uchun kerak #

Sxemasiz baza tez rivojlanish uchun qulay. Lekin loyiha o'sgan sari quyidagilar paydo bo'ladi:

MuammoMisol
Bir maydon, ikki turnarx: 85000 va narx: "85000"
Yozuv xatosilavozim o'rniga lavozom
Majburiy maydon yo'qYarim to'ldirilgan hujjat
Ma'nosiz qiymatmaosh: -5000

Bularning hech biri darhol ko'rinmaydi. Ular bir necha oydan keyin, hisobot noto'g'ri chiqqanda ma'lum bo'ladi.

Qoida ishlayaptimi #

To'g'ri hujjat muammosiz qo'shiladi:

JavaScript
db.xodim.insertOne({
  _id: 3, ism: "Nodira", lavozim: "menejer", maosh: Int32(8200000)
})
Natija
{ acknowledged: true, insertedId: 3 }

Endi qoidani buzamiz - majburiy maydonsiz:

JavaScript
db.xodim.insertOne({ _id: 4, ism: "Aziza", lavozim: "dasturchi" })
Natija
Uncaught:
MongoServerError: Document failed validation
Additional information: {
  failingDocumentId: 4,
  details: {
    operatorName: '$jsonSchema',
    schemaRulesNotSatisfied: [
      {
        operatorName: 'required',
        specifiedAs: { required: [ 'ism', 'lavozim', 'maosh' ] },
        missingProperties: [ 'maosh' ]
      }
    ]
  }
}

Xato xabari uzun, lekin undagi eng muhim qism - missingProperties ro'yxati.

Ro'yxatda yo'q lavozim:

JavaScript
db.xodim.insertOne({
  _id: 5, ism: "Kamola", lavozim: "direktor", maosh: Int32(12000000)
})
Natija
Uncaught:
MongoServerError: Document failed validation
Additional information: {
  failingDocumentId: 5,
  details: {
    operatorName: '$jsonSchema',
    schemaRulesNotSatisfied: [
      {
        operatorName: 'properties',
        propertiesNotSatisfied: [
          {
            propertyName: 'lavozim',
            description: "lavozim ro'yxatdagi qiymatlardan biri bo'lsin",
            details: [
              {
                operatorName: 'enum',
                specifiedAs: { enum: [ 'dasturchi', 'tahlilchi', 'menejer' ] },
                reason: 'value was not found in enum',
                consideredValue: 'direktor'
              }
            ]
          }
        ]
      }
    ]
  }
}

Noto'g'ri tur:

JavaScript
db.xodim.insertOne({
  _id: 6, ism: "Dilnoza", lavozim: "tahlilchi", maosh: 6000000.5
})
Natija
Uncaught:
MongoServerError: Document failed validation
Additional information: {
  failingDocumentId: 6,
  details: {
    operatorName: '$jsonSchema',
    schemaRulesNotSatisfied: [
      {
        operatorName: 'properties',
        propertiesNotSatisfied: [
          {
            propertyName: 'maosh',
            description: "maosh butun son va 1 000 000 dan katta bo'lsin",
            details: [
              {
                operatorName: 'bsonType',
                specifiedAs: { bsonType: 'int' },
                reason: 'type did not match',
                consideredValue: 6000000.5,
                consideredType: 'double'
              }
            ]
          }
        ]
      }
    ]
  }
}

maosh uchun bsonType: "int" talab qilingan, kasr son esa double hisoblanadi.

bsonType: "int" - mongosh da tuzoq

mongosh JavaScript ustida ishlaydi, JavaScript da esa oddiy 9000000 yozuvi double turiga aylanadi.

Shuning uchun bu hujjat qoidani buzadi:

Natija
db.xodim.insertOne({ ism: "Anvar", lavozim: "menejer", maosh: 9000000 })

To'g'ri yozuv - turni ochiq ko'rsatish:

Natija
maosh: Int32(9000000)

Uchta yechim bor:

YechimQachon
Int32(...) yozishQo'lda kiritishda
bsonType: ["int", "long", "double"]Turi muhim bo'lmasa
bsonType: "number"Har qanday son bo'lsa yetarli

Dastur kutubxonalari (Node.js, Python) odatda turni to'g'ri jo'natadi, shuning uchun bu muammo asosan qo'lda sinov paytida uchraydi.

Asosiy kalit so'zlar #

KalitMa'nosi
bsonTypeMaydon turi: string, int, double, bool, date, array, object
requiredMajburiy maydonlar ro'yxati
enumFaqat sanalgan qiymatlar
minimum / maximumSon chegarasi
minLength / maxLengthMatn uzunligi
patternMuntazam ifoda
minItems / maxItemsMassiv uzunligi
uniqueItemsMassivda takror bo'lmasin
additionalPropertiesRo'yxatda yo'q maydonga ruxsat
descriptionXato xabarida ko'rinadi
description ni har doim yozing

description shunchaki izoh emas - u xato xabarida ko'rsatiladi.

Usiz dastur quyidagini oladi:

Natija
Document failed validation

Bu bilan nima noto'g'ri ekanini tushunib bo'lmaydi. description bo'lsa, xato aniq aytadi: "maosh butun son va 1 000 000 dan katta bo'lishi kerak".

Bu matn foydalanuvchiga ko'rsatiladigan xabar emas, lekin u jurnalga tushadi va muammoni bir necha soatga emas, bir necha daqiqaga qisqartiradi.

validationLevel va validationAction #

Ikkita sozlama qoidaning qanchalik qattiq ishlashini belgilaydi:

Ikkita sozlama, to'rtta xatti-harakat validationLevel strict - hamma yozuv tekshiriladi moderate - faqat qoidaga mos bo'lgan hujjatlar yangilanganda validationAction error - yozuvni rad etadi warn - yozadi, lekin jurnalga ogohlantirish qo'yadi Mavjud to'plamga qoida qo'shishning to'g'ri tartibi 1. warn + moderate bilan boshlang - hech narsa buzilmaydi 2. Jurnalni kuzating va eski hujjatlarni tuzating 3. Ogohlantirish to'xtagach error + strict ga o'ting
Ishlab turgan tizimga birdaniga strict qo'yish - yozuvlarni to'xtatib qo'yadi

Mavjud to'plamga qoida qo'shish #

Ichida allaqachon nomuvofiq hujjat bo'lgan to'plamga qoida qo'yamiz. warn rejimi hech narsani to'xtatmaydi:

JavaScript
db.mahsulot.insertMany([
  { _id: 1, nom: "Noutbuk", narx: 8500000 },
  { _id: 2, nom: "Sichqoncha" }
])
db.runCommand({
  collMod: "mahsulot",
  validator: { $jsonSchema: {
    bsonType: "object",
    required: ["nom", "narx"]
  } },
  validationLevel: "moderate",
  validationAction: "warn"
}).ok
db.mahsulot.insertOne({ _id: 3, nom: "Klaviatura" })
db.mahsulot.countDocuments()
Natija
{ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }
1
{ acknowledged: true, insertedId: 3 }
3

Uchinchi hujjatda narx yo'q edi, lekin u baribir yozildi - faqat serverning jurnaliga ogohlantirish tushdi.

Endi xuddi shu qoidani error rejimida qo'yamiz:

JavaScript
db.mahsulot.insertMany([
  { _id: 1, nom: "Noutbuk", narx: 8500000 },
  { _id: 2, nom: "Sichqoncha" }
])
db.runCommand({
  collMod: "mahsulot",
  validator: { $jsonSchema: {
    bsonType: "object",
    required: ["nom", "narx"]
  } },
  validationLevel: "moderate",
  validationAction: "error"
}).ok
db.mahsulot.insertOne({ _id: 3, nom: "Klaviatura" })
db.mahsulot.countDocuments()
Natija
{ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }
1
Uncaught:
MongoServerError: Document failed validation
Additional information: {
  failingDocumentId: 3,
  details: {
    operatorName: '$jsonSchema',
    schemaRulesNotSatisfied: [
      {
        operatorName: 'required',
        specifiedAs: { required: [ 'nom', 'narx' ] },
        missingProperties: [ 'narx' ]
      }
    ]
  }
}
2

Bu safar yangi hujjat rad etildi. Lekin eski _id: 2 hujjati - u ham narx siz - joyida turibdi:

JavaScript
db.mahsulot.insertMany([
  { _id: 1, nom: "Noutbuk", narx: 8500000 },
  { _id: 2, nom: "Sichqoncha" }
])
db.runCommand({
  collMod: "mahsulot",
  validator: { $jsonSchema: {
    bsonType: "object",
    required: ["nom", "narx"]
  } },
  validationLevel: "moderate",
  validationAction: "error"
}).ok
db.mahsulot.updateOne({ _id: 2 }, { $set: { rang: "qora" } })
db.mahsulot.findOne({ _id: 2 })
Natija
{ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }
1
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
{ _id: 2, nom: 'Sichqoncha', rang: 'qora' }

moderate shuning uchun kerak: eski nomuvofiq hujjatni yangilashga ruxsat beradi. Endi bitta so'zni - moderate o'rniga strict - o'zgartiramiz:

JavaScript
db.mahsulot.insertMany([
  { _id: 1, nom: "Noutbuk", narx: 8500000 },
  { _id: 2, nom: "Sichqoncha" }
])
db.runCommand({
  collMod: "mahsulot",
  validator: { $jsonSchema: {
    bsonType: "object",
    required: ["nom", "narx"]
  } },
  validationLevel: "strict",
  validationAction: "error"
}).ok
db.mahsulot.updateOne({ _id: 2 }, { $set: { rang: "qora" } })
Natija
{ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }
1
Uncaught:
MongoServerError: Plan executor error during update :: caused by :: Document failed validation
Additional information: {
  failingDocumentId: 2,
  details: {
    operatorName: '$jsonSchema',
    schemaRulesNotSatisfied: [
      {
        operatorName: 'required',
        specifiedAs: { required: [ 'nom', 'narx' ] },
        missingProperties: [ 'narx' ]
      }
    ]
  }
}

Xuddi shu updateOne endi rad etildi - garchi u narx ga umuman tegmagan bo'lsa ham. Aynan shu quyidagi ogohlantirishning mohiyati.

strict + error ni ishlab turgan tizimga birdan qo'ymang

Bu eng ko'p uchraydigan joylashtirish falokati.

Sizda million hujjat bor, ulardan 3 tasida email maydoni yo'q. Siz required: ["email"] qo'yasiz va strict + error rejimini yoqasiz.

Nima bo'ladi:

AmalNatija
Yangi hujjat qo'shishIshlaydi (email bor)
Eski uch hujjatni yangilashXato

Uchta foydalanuvchi endi profilini yangilay olmaydi. Xato esa "email required" - garchi ular emailga umuman tegmagan bo'lsa ham.

moderate aynan shu holat uchun: u faqat allaqachon qoidaga mos hujjatlarni tekshiradi. Eski nomuvofiq hujjatlar tuzatilgunicha ishlayveradi.

To'g'ri tartib: warn + moderate -> tuzatish -> error + moderate -> to'liq tozalangach strict.

Qoidani ko'rish va olib tashlash #

JavaScript
const m = db.getCollectionInfos({ name: "xodim" })[0]
m.options.validationLevel
m.options.validationAction
m.options.validator.$jsonSchema.required
Natija
strict
error
[ 'ism', 'lavozim', 'maosh' ]

Qoidani butunlay olib tashlash uchun bo'sh validator beriladi:

JavaScript
db.runCommand({ collMod: "xodim", validator: {} }).ok
db.xodim.insertOne({ _id: 9, ism: "A", lavozim: "hech kim" })
db.xodim.countDocuments()
Natija
1
{ acknowledged: true, insertedId: 9 }
3

Endi hech qanday tekshiruv yo'q - hatto ism ham ikki belgidan qisqa bo'lishi mumkin.

Qoida qayerda bo'lishi kerak #

Sxema tekshiruvi dastur darajasidagi tekshiruvni almashtirmaydi:

QavatNima tekshiradiNima uchun
InterfeysBo'sh maydon, formatFoydalanuvchiga tez javob
DasturBiznes qoidalariMurakkab shartlar
BazaTuzilma va turlarOxirgi himoya

Baza qavati oxirgi himoya bo'lgani uchun muhim: unga faqat dastur emas, migratsiya skriptlari, qo'lda yozilgan buyruqlar va boshqa xizmatlar ham tegadi.

Amaliy topshiriq
  1. $jsonSchema bilan to'plam yarating.
  2. Uchta majburiy maydon belgilang.
  3. enum bilan ruxsat etilgan qiymatlarni cheklang.
  4. Qoidaga mos hujjat qo'shing.
  5. Majburiy maydonsiz hujjat qo'shib, xatoni o'qing.
  6. description nega muhimligini tushuntiring.
  7. Int32(...) nega kerak bo'lishini yozing.
  8. Mavjud to'plamga collMod bilan qoida qo'shing.
  9. warn rejimida noto'g'ri hujjat yoziladimi - sinang.
  10. strict ni birdan yoqish qanday muammo tug'dirishini yozing.

Xulosa #

  • MongoDB sxemani talab qilmaydi, lekin uni $jsonSchema bilan majburlash mumkin.
  • required majburiy maydonlarni, bsonType esa turlarni belgilaydi.
  • enum, minimum, pattern, minItems kabi cheklovlar mavjud.
  • description ni har doim yozing - u xato xabarida ko'rinadi.
  • mongosh da oddiy son double bo'ladi - bsonType: "int" uchun Int32(...) kerak.
  • validationLevel: strict hammasini, moderate faqat mos hujjatlarni tekshiradi.
  • validationAction: error rad etadi, warn esa yozadi va jurnalga qayd qiladi.
  • Mavjud to'plamga qoida collMod buyrug'i bilan qo'shiladi.
  • Ishlab turgan tizimga strict + error ni birdan qo'ymang - eski hujjatlar yangilanmay qoladi.
  • Baza tekshiruvi dastur tekshiruvini almashtirmaydi - u oxirgi himoya.

Keyingi bo'limda agregatsiya quvuri bilan tanishamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.