Ma'lumot turlari — String, Number, Boolean, Date, ObjectId, Array, Object, Null
Muammodan boshlaylik
db.mahsulotlar.insertOne({ narx: "12500" })
db.mahsulotlar.insertOne({ narx: 12500 })
Bu ikki document ko'rinishda o'xshash. Lekin biri string, biri raqam.
Farqi? Birinchisida narx > 10000 so'rovi ishlamaydi — string bilan
raqamni solishtirish mumkin emas. Sort ham noto'g'ri ishlaydi.
Ma'lumot turini noto'g'ri tanlash — keyinchalik topish qiyin bo'lgan xatolarga olib keladi. Bu darsda har bir turni tushunib olamiz.
MongoDB BSON tiplari — umumiy ko'rinish
┌─────────────────┬──────────────┬───────────────────────────────────┐
│ Tip nomi │ Misol │ Qachon ishlatish │
├─────────────────┼──────────────┼───────────────────────────────────┤
│ String │ "Jasur" │ Matn ma'lumotlari │
│ Int32 │ 24 │ Kichik butun sonlar (-2B..+2B) │
│ Int64 (Long) │ 9007199... │ Katta butun sonlar │
│ Double │ 19.99 │ Kasr sonlar │
│ Decimal128 │ 19.9900... │ Moliyaviy aniq kasr │
│ Boolean │ true/false │ Ha/Yo'q holatlari │
│ Date │ ISODate(…) │ Vaqt va sana │
│ ObjectId │ ObjectId(…) │ Unikal identifikator (_id) │
│ Array │ [1, 2, 3] │ Ro'yxat, bir nechta qiymat │
│ Object │ { a: 1 } │ Ichma-ich hujjat │
│ Null │ null │ Qiymat yo'qligi (qasdan) │
│ Regex │ /pattern/ │ Pattern bilan qidirish │
│ Binary (BinData│ BinData(…) │ Fayllar, rasmlar (GridFS yaxshi) │
└─────────────────┴──────────────┴───────────────────────────────────┘
Keling, har birini alohida ko'raylik.
1. String
Matnli ma'lumotlar uchun. UTF-8 kodlashda saqlanadi — o'zbek, rus, arab harflari ham ishlaydi.
db.foydalanuvchilar.insertOne({
ism: "Jasur",
familiya: "Karimov",
shahar: "Тошкент", // ← rus harflari
izoh: "مرحبا", // ← arab harflari
email: "jasur@mail.uz"
})
String bilan foydali so'rovlar
// Aniq mos
db.users.find({ ism: "Jasur" })
// Regex bilan — "Jas" bilan boshlanadigan
db.users.find({ ism: /^Jas/ })
// Katta-kichik harfdan qat'iy nazar
db.users.find({ ism: /jasur/i })
// $regex operatori (bir xil)
db.users.find({ ism: { $regex: "jasur", $options: "i" } })
SQL bilan solishtiring:
-- SQL
SELECT * FROM users WHERE ism LIKE 'Jas%';
SELECT * FROM users WHERE LOWER(ism) = 'jasur';
// MongoDB
db.users.find({ ism: /^Jas/ })
db.users.find({ ism: /^jasur$/i })
2. Number — uchta tur
Bu ko'pchilikni chalg'itadigan joy. MongoDB da uchta raqam turi bor:
┌─────────────────┬──────────────────────────────┬─────────────────────┐
│ Tur │ Diapazon │ Qaerda ishlatish │
├─────────────────┼──────────────────────────────┼─────────────────────┤
│ Int32 │ -2,147,483,648 │ Yosh, soni, ball │
│ (oddiy int) │ +2,147,483,647 │ │
├─────────────────┼──────────────────────────────┼─────────────────────┤
│ Int64 / Long │ -9.2 × 10^18 │ ID, timestamp, │
│ │ +9.2 × 10^18 │ juda katta sonlar │
├─────────────────┼──────────────────────────────┼─────────────────────┤
│ Double │ ±5.0 × 10^-324 dan │ Narx, foiz, │
│ (float) │ ±1.7 × 10^308 gacha │ koordinatalar │
├─────────────────┼──────────────────────────────┼─────────────────────┤
│ Decimal128 │ 34 ta aniq raqam │ Moliya, bank, │
│ │ (IEEE 754-2008) │ valyuta kursi │
└─────────────────┴──────────────────────────────┴─────────────────────┘
Mongosh da yozilishi
db.mahsulotlar.insertOne({
soni: 150, // ← oddiy son (Int32)
narx: 19.99, // ← kasr (Double)
aniq_narx: NumberDecimal("19.99"), // ← moliya uchun aniq kasr
})
Oddiy raqam yozsangiz — 19.99 — MongoDB Double saqlaydi.
Nima uchun Decimal128 muhim?
// Double (IEEE 754 muammosi)
0.1 + 0.2
// 0.30000000000000004 ← noto'g'ri!
// Decimal128
NumberDecimal("0.1") + NumberDecimal("0.2")
// 0.3 ← to'g'ri!
Bank tizimida 0.30000000000000004 so'm farq juda katta muammo.
Moliyaviy hisob-kitoblarda doim Decimal128 ishlating.
Raqam bilan so'rovlar
// Tenglik
db.talabalar.find({ yosh: 24 })
// Taqqoslash
db.talabalar.find({ yosh: { $gt: 20 } }) // yosh > 20
db.talabalar.find({ yosh: { $gte: 18 } }) // yosh >= 18
db.talabalar.find({ yosh: { $lt: 30 } }) // yosh < 30
db.talabalar.find({ yosh: { $lte: 25 } }) // yosh <= 25
// Oraliq
db.talabalar.find({ yosh: { $gte: 18, $lte: 25 } })
SQL bilan:
-- SQL
SELECT * FROM talabalar WHERE yosh > 20;
SELECT * FROM talabalar WHERE yosh BETWEEN 18 AND 25;
// MongoDB
db.talabalar.find({ yosh: { $gt: 20 } })
db.talabalar.find({ yosh: { $gte: 18, $lte: 25 } })
3. Boolean
Faqat ikki qiymat: true yoki false.
db.foydalanuvchilar.insertOne({
ism: "Jasur",
faol: true, // ← aktiv foydalanuvchi
email_tasdig: false, // ← email tasdiqlanmagan
premium: false
})
Boolean bilan so'rovlar
// Faol foydalanuvchilar
db.foydalanuvchilar.find({ faol: true })
// Email tasdiqlanmaganlar
db.foydalanuvchilar.find({ email_tasdig: false })
SQL bilan:
-- SQL
SELECT * FROM foydalanuvchilar WHERE faol = TRUE;
// MongoDB
db.foydalanuvchilar.find({ faol: true })
Diqqat: "truthy" va "falsy" ishlamaydi
// ❌ Bu XATO — "true" string, boolean emas
db.users.insertOne({ faol: "true" })
db.users.find({ faol: true }) // bu user topilmaydi!
// ✅ To'g'ri
db.users.insertOne({ faol: true })
db.users.find({ faol: true }) // topiladi
4. Date
Vaqt va sana ma'lumotlari uchun. UTC da saqlanadi.
Ichki ko'rinish:
┌──────────────────────────────────────────────────────┐
│ ISODate("2024-03-15T09:30:00.000Z") │
│ ────────── ──────────── │
│ Sana Vaqt (UTC) │
└──────────────────────────────────────────────────────┘
db.voqealar.insertOne({
sarlavha: "Uchrashuv",
boshlanish: new Date(), // ← hozir
tugash: new Date("2024-03-15T18:00:00.000Z"), // ← aniq vaqt
yaratilgan: ISODate("2024-03-15") // ← faqat sana
})
Date bilan so'rovlar
// Bugundan keyin bo'lgan voqealar
db.voqealar.find({
boshlanish: { $gt: new Date() }
})
// 2024-yil mart oyidagi voqealar
db.voqealar.find({
boshlanish: {
$gte: new Date("2024-03-01"),
$lt: new Date("2024-04-01")
}
})
SQL bilan:
-- SQL
SELECT * FROM voqealar WHERE boshlanish > NOW();
SELECT * FROM voqealar
WHERE boshlanish >= '2024-03-01'
AND boshlanish < '2024-04-01';
Muhim: Date ni string sifatida saqlamang
// ❌ Yomon — sort ishlamaydi, solishtirish noto'g'ri
{ yaratilgan: "2024-03-15" }
// ✅ Yaxshi — native Date
{ yaratilgan: new Date("2024-03-15") }
String "2024-03-15" va "2023-12-31" ni solishtirsa — string
solishtirish "2024" > "2023" to'g'ri, lekin "2024-01-01" va
"2023-12-31" da string "2023" < "2024" — bu tasodifan to'g'ri.
Ammo murakkab hollarda noto'g'ri natija beradi. Shuning uchun
doim native Date ishlating.
5. ObjectId
Avvalgi darsda ko'rdik. Qisqacha eslatma:
ObjectId("64a1f2c3 b4e5f6 a7b8 c9d0e1")
──────── ────── ──── ──────
Timestamp Mashina PID Random
(4 bayt) (3 bayt) (2B) (3 bayt)
Jami: 12 bayt = 24 hex belgi
// Yangi ObjectId yaratish
let id = new ObjectId()
id.toString() // "64a1f2c3b4e5f6a7b8c9d0e1"
id.getTimestamp() // ISODate("2024-03-15T09:30:43.000Z")
// _id bo'yicha qidirish
db.talabalar.findOne({ _id: ObjectId("64a1f2c3b4e5f6a7b8c9d0e1") })
// ❌ Bu ishlamaydi — string va ObjectId farqli tiplar
db.talabalar.findOne({ _id: "64a1f2c3b4e5f6a7b8c9d0e1" })
6. Array (Massiv)
Bitta maydonning bir nechta qiymat saqlashi. MongoDB ning kuchli tomonlaridan biri.
db.talabalar.insertOne({
ism: "Jasur",
hobbylar: ["dasturlash", "futbol", "kitob"], // ← string array
baholar: [85, 92, 78, 95], // ← raqam array
taglar: [], // ← bo'sh array
})
Array ichida qidirish
MongoDB massiv ichida qidirish uchun maxsus sintaksis talab qilmaydi:
// "futbol" hobbysi bor talabalar
db.talabalar.find({ hobbylar: "futbol" })
// ← MongoDB massiv ichida avtomatik qidiradi
// Bir nechta qiymatdan kamida biri bo'lishi
db.talabalar.find({ hobbylar: { $in: ["futbol", "basketbol"] } })
// Ikkalasi ham bo'lishi
db.talabalar.find({ hobbylar: { $all: ["futbol", "kitob"] } })
// Massiv uzunligi
db.talabalar.find({ hobbylar: { $size: 3 } })
SQL bilan solishtiring — SQL da massiv yo'q, alohida jadval kerak:
-- SQL: alohida jadval va JOIN
SELECT t.*
FROM talabalar t
JOIN hobbylar h ON t.id = h.talaba_id
WHERE h.hobby = 'futbol';
// MongoDB: bitta so'rov, join yo'q
db.talabalar.find({ hobbylar: "futbol" })
Array ichida raqam solishtirish
// Baholardan kamida biri 90 dan yuqori bo'lganlar
db.talabalar.find({ baholar: { $gt: 90 } })
// ← massiv ichidagi har bir element tekshiriladi
// Baholardan kamida biri 80 dan yuqori VA 95 dan past
db.talabalar.find({
baholar: { $elemMatch: { $gt: 80, $lt: 95 } }
})
// $elemMatch — bitta element ikki shartni qondirishini tekshiradi
7. Object (Embedded Document)
Ichma-ich hujjat — bir document boshqa documentni o'z ichiga oladi.
db.talabalar.insertOne({
ism: "Jasur",
manzil: { // ← ichma-ich object
shahar: "Toshkent",
tuman: "Chilonzor",
pochta: 100301
},
diplom: { // ← yana bir ichma-ich object
daraja: "Bakalavr",
mutaxassis: "Informatika",
yil: 2024
}
})
Ichki maydonlarga so'rov — dot notation
// Chilonzorda yashovchilar
db.talabalar.find({ "manzil.tuman": "Chilonzor" })
// ↑↑↑ qo'shtirnoq majburiy
// Informatika mutaxassislar
db.talabalar.find({ "diplom.mutaxassis": "Informatika" })
// Ikki darajali ichki so'rov
db.maktablar.find({ "rektor.lavozim.unvon": "Professor" })
Ichki object ni to'liq solishtirish — ehtiyot bo'ling
// ❌ Bu faqat manzil AYNAN { shahar: "Toshkent" } bo'lganda ishlaydi
// tuman, pochta qo'shilsa — topilmaydi
db.talabalar.find({ manzil: { shahar: "Toshkent" } })
// ✅ To'g'ri — faqat kerakli maydonni tekshiradi
db.talabalar.find({ "manzil.shahar": "Toshkent" })
8. Null
Maydon mavjud lekin qiymati yo'q — maqsadli bo'sh.
db.foydalanuvchilar.insertOne({
ism: "Jasur",
o_chirilgan: null, // ← hali o'chirilmagan, lekin maydon bor
so_nggi_kiris: null // ← hali kirmagan
})
Null va mavjud emas — farqi bor
┌────────────────────────────────────────────────────────┐
│ Document A: { ism: "Jasur", telefon: null } │
│ Document B: { ism: "Malika" } │
│ ↑ telefon maydon yo'q │
└────────────────────────────────────────────────────────┘
// Ikkalasi ham topiladi — null ham, yo'q ham
db.users.find({ telefon: null })
// → Document A (telefon: null)
// → Document B (telefon maydoni yo'q)
// Faqat null qiymatlilarni topish
db.users.find({ telefon: { $type: "null" } })
// → faqat Document A
// Faqat maydoni yo'qlarni topish
db.users.find({ telefon: { $exists: false } })
// → faqat Document B
// Maydoni borlarni topish (null bo'lsa ham)
db.users.find({ telefon: { $exists: true } })
// → faqat Document A
SQL bilan:
-- SQL
SELECT * FROM users WHERE telefon IS NULL;
-- SQL da "ustun yo'q" va "NULL" farqlanmaydi
MongoDB da bu farq muhim — shuning uchun $exists va $type
operatorlari bor.
Hamma tiplarni bitta documentda ko'rish
db.namuna.insertOne({
matn: "Salom", // String
butun: NumberInt(42), // Int32
kasr: 3.14, // Double
aniq_kasr: NumberDecimal("9.99"), // Decimal128
mantiqiy: true, // Boolean
sana: new Date(), // Date
id: new ObjectId(), // ObjectId
royxat: ["a", "b", "c"], // Array
ichki: { a: 1, b: 2 }, // Object
bosh: null, // Null
regex: /pattern/i // RegExp
})
Tip tekshirish — $type operatori
Ma'lumotlar bazasida noto'g'ri tip saqlanib qolgan bo'lsa, topish uchun:
// narx string saqlanganlar — xato ma'lumotlar
db.mahsulotlar.find({ narx: { $type: "string" } })
// narx raqam saqlanganlar — to'g'ri
db.mahsulotlar.find({ narx: { $type: "number" } })
Tez-tez uchraydigan xatolar
Narxni string saqlash
// ❌ String sifatida saqlagan
db.mahsulotlar.insertMany([
{ nom: "Kitob", narx: "25000" },
{ nom: "Qalam", narx: "5000" },
])
db.mahsulotlar.find({ narx: { $gt: 10000 } })
// ← Hech narsa topilmaydi — "25000" string, raqam emas
db.mahsulotlar.find().sort({ narx: 1 })
// ← Noto'g'ri sort: "25000", "5000" (string sort: "2" < "5")
// To'g'ri bo'lishi kerak: 5000, 25000 (raqam sort)
Sabab: frontend yoki API dan kelgan ma'lumotlar ba'zan string bo'lib keladi. Saqlashdan oldin tipni tekshiring yoki Mongoose validation ishlating.
Date ni string saqlash
// ❌ String — sort noto'g'ri, oraliq so'rov ishlamaydi
{ yaratilgan: "15-03-2024" }
// ✅ Native Date — sort to'g'ri, oraliq so'rov ishlaydi
{ yaratilgan: new Date("2024-03-15") }
null va undefined farqi
// undefined — BSON da yo'q, MongoDB qabul qilmaydi
db.users.insertOne({ ism: "Jasur", telefon: undefined })
// → telefon maydoni umuman saqlanmaydi
// null — BSON da bor, maxsus qiymat
db.users.insertOne({ ism: "Jasur", telefon: null })
// → { ism: "Jasur", telefon: null }
Mongoose da ham shu qoida: undefined o'tkazmang, null yoki
maydonni tashlab keting.
Xulosa
┌─────────────┬────────────────────────────────────────────┐
│ String │ Matn, UTF-8, regex bilan qidirish │
│ Int32 │ Kichik butun son (-2B..+2B) │
│ Double │ Kasr son, default raqam turi │
│ Decimal128 │ Moliyaviy aniq kasr — bank, narx │
│ Boolean │ true / false — qat'iy tip │
│ Date │ UTC da, native Date ishlating │
│ ObjectId │ _id uchun, timestamp o'z ichida │
│ Array │ Ro'yxat, ichida qidirish mumkin │
│ Object │ Ichma-ich document, dot notation │
│ Null │ Qiymat yo'q (maydon yo'q ≠ null) │
└─────────────┴────────────────────────────────────────────┘
Asosiy qoidalar:
- Narx, yosh, soni → raqam tur, string emas
- Sana →
new Date(), string emas - Moliyaviy hisob →
NumberDecimal, Double emas nullva maydon yo'qligi — ikki xil holat,$existsbilan farqlash
Keyingi dars: 6-dars — insertOne, insertMany: hujjat qo'shish