11-bo‘lim
Sxema tekshiruvi
$jsonSchema bilan qoida yozish, majburiy maydonlar va turlar, validationLevel va validationAction, mavjud to'plamga qoida qo'shish.
Ushbu bo‘lim mundarijasi
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.
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:
| Muammo | Misol |
|---|---|
| Bir maydon, ikki tur | narx: 85000 va narx: "85000" |
| Yozuv xatosi | lavozim o'rniga lavozom |
| Majburiy maydon yo'q | Yarim to'ldirilgan hujjat |
| Ma'nosiz qiymat | maosh: -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:
db.xodim.insertOne({
_id: 3, ism: "Nodira", lavozim: "menejer", maosh: Int32(8200000)
})
{ acknowledged: true, insertedId: 3 }
Endi qoidani buzamiz - majburiy maydonsiz:
db.xodim.insertOne({ _id: 4, ism: "Aziza", lavozim: "dasturchi" })
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:
db.xodim.insertOne({
_id: 5, ism: "Kamola", lavozim: "direktor", maosh: Int32(12000000)
})
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:
db.xodim.insertOne({
_id: 6, ism: "Dilnoza", lavozim: "tahlilchi", maosh: 6000000.5
})
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 tuzoqmongosh JavaScript ustida ishlaydi, JavaScript da esa
oddiy 9000000 yozuvi double turiga aylanadi.
Shuning uchun bu hujjat qoidani buzadi:
db.xodim.insertOne({ ism: "Anvar", lavozim: "menejer", maosh: 9000000 })
To'g'ri yozuv - turni ochiq ko'rsatish:
maosh: Int32(9000000)
Uchta yechim bor:
| Yechim | Qachon |
|---|---|
Int32(...) yozish | Qo'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 #
| Kalit | Ma'nosi |
|---|---|
bsonType | Maydon turi: string, int, double, bool, date, array, object |
required | Majburiy maydonlar ro'yxati |
enum | Faqat sanalgan qiymatlar |
minimum / maximum | Son chegarasi |
minLength / maxLength | Matn uzunligi |
pattern | Muntazam ifoda |
minItems / maxItems | Massiv uzunligi |
uniqueItems | Massivda takror bo'lmasin |
additionalProperties | Ro'yxatda yo'q maydonga ruxsat |
description | Xato xabarida ko'rinadi |
description ni har doim yozingdescription shunchaki izoh emas - u xato xabarida
ko'rsatiladi.
Usiz dastur quyidagini oladi:
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:
Mavjud to'plamga qoida qo'shish #
Ichida allaqachon nomuvofiq hujjat bo'lgan to'plamga qoida
qo'yamiz. warn rejimi hech narsani to'xtatmaydi:
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()
{ 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:
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()
{ 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:
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 })
{ 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:
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" } })
{ 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'ymangBu 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:
| Amal | Natija |
|---|---|
| Yangi hujjat qo'shish | Ishlaydi (email bor) |
| Eski uch hujjatni yangilash | Xato |
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 #
const m = db.getCollectionInfos({ name: "xodim" })[0]
m.options.validationLevel
m.options.validationAction
m.options.validator.$jsonSchema.required
strict
error
[ 'ism', 'lavozim', 'maosh' ]
Qoidani butunlay olib tashlash uchun bo'sh validator beriladi:
db.runCommand({ collMod: "xodim", validator: {} }).ok
db.xodim.insertOne({ _id: 9, ism: "A", lavozim: "hech kim" })
db.xodim.countDocuments()
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:
| Qavat | Nima tekshiradi | Nima uchun |
|---|---|---|
| Interfeys | Bo'sh maydon, format | Foydalanuvchiga tez javob |
| Dastur | Biznes qoidalari | Murakkab shartlar |
| Baza | Tuzilma va turlar | Oxirgi himoya |
Baza qavati oxirgi himoya bo'lgani uchun muhim: unga faqat dastur emas, migratsiya skriptlari, qo'lda yozilgan buyruqlar va boshqa xizmatlar ham tegadi.
$jsonSchemabilan to'plam yarating.- Uchta majburiy maydon belgilang.
enumbilan ruxsat etilgan qiymatlarni cheklang.- Qoidaga mos hujjat qo'shing.
- Majburiy maydonsiz hujjat qo'shib, xatoni o'qing.
descriptionnega muhimligini tushuntiring.Int32(...)nega kerak bo'lishini yozing.- Mavjud to'plamga
collModbilan qoida qo'shing. warnrejimida noto'g'ri hujjat yoziladimi - sinang.strictni birdan yoqish qanday muammo tug'dirishini yozing.
Xulosa #
- MongoDB sxemani talab qilmaydi, lekin uni
$jsonSchemabilan majburlash mumkin. requiredmajburiy maydonlarni,bsonTypeesa turlarni belgilaydi.enum,minimum,pattern,minItemskabi cheklovlar mavjud.descriptionni har doim yozing - u xato xabarida ko'rinadi.- mongosh da oddiy son
doublebo'ladi -bsonType: "int"uchunInt32(...)kerak. validationLevel:stricthammasini,moderatefaqat mos hujjatlarni tekshiradi.validationAction:errorrad etadi,warnesa yozadi va jurnalga qayd qiladi.- Mavjud to'plamga qoida
collModbuyrug'i bilan qo'shiladi. - Ishlab turgan tizimga
strict+errorni birdan qo'ymang - eski hujjatlar yangilanmay qoladi. - Baza tekshiruvi dastur tekshiruvini almashtirmaydi - u oxirgi himoya.
Keyingi bo'limda agregatsiya quvuri bilan tanishamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.