find, findOne — filter, projection, sort, limit, skip
Muammodan boshlaylik
Ma'lumotlar bazasida 10,000 ta foydalanuvchi bor. Sizga kerak:
- Faqat Toshkentliklar
- Faqat ism va email — telefon, parol ko'rsatma
- Yoshiga qarab tartiblangan
- Faqat birinchi 20 tasi
Bu to'rtta talabni SQL da SELECT, WHERE, ORDER BY, LIMIT bilan
qilasiz. MongoDB da esa find() ning parametrlari bilan.
find() — asosiy tuzilish
db.<collection>.find(<filter>, <projection>)
↑ ↑
Qaysilarni Qaysi maydonlar
topish ko'rinsin
SQL bilan parallel:
SELECT ism, email -- projection
FROM foydalanuvchilar -- collection
WHERE shahar = 'Toshkent' -- filter
db.foydalanuvchilar.find(
{ shahar: "Toshkent" }, // filter
{ ism: 1, email: 1 } // projection
)
Filter — qaysi documentlar
Bo'sh filter — hammasi
db.talabalar.find() // barcha documentlar
db.talabalar.find({}) // bir xil — {} bo'sh filter
Aniq qiymat bilan
// Shahar bo'yicha
db.talabalar.find({ shahar: "Toshkent" })
// Bir nechta shart — AND (ikkalasi ham bo'lishi kerak)
db.talabalar.find({ shahar: "Toshkent", sinf: "10A" })
SQL:
SELECT * FROM talabalar WHERE shahar = 'Toshkent';
SELECT * FROM talabalar WHERE shahar = 'Toshkent' AND sinf = '10A';
Solishtirish operatorlari
┌──────────┬──────────────┬──────────────────────────────────┐
│ Operator │ Ma'nosi │ Misol │
├──────────┼──────────────┼──────────────────────────────────┤
│ $eq │ = │ { yosh: { $eq: 24 } } │
│ $ne │ != │ { yosh: { $ne: 24 } } │
│ $gt │ > │ { yosh: { $gt: 18 } } │
│ $gte │ >= │ { yosh: { $gte: 18 } } │
│ $lt │ < │ { yosh: { $lt: 30 } } │
│ $lte │ <= │ { yosh: { $lte: 30 } } │
│ $in │ ichida bor │ { shahar: { $in: ["TK","SQ"] }} │
│ $nin │ ichida yo'q │ { shahar: { $nin: ["TK"] } } │
└──────────┴──────────────┴──────────────────────────────────┘
// 18 yoshdan katta
db.talabalar.find({ yosh: { $gt: 18 } })
// 18 va 25 orasida (oraliq)
db.talabalar.find({ yosh: { $gte: 18, $lte: 25 } })
// Toshkent yoki Samarqandda
db.talabalar.find({ shahar: { $in: ["Toshkent", "Samarqand"] } })
// Toshkentda emas
db.talabalar.find({ shahar: { $nin: ["Toshkent"] } })
SQL bilan:
SELECT * FROM talabalar WHERE yosh > 18;
SELECT * FROM talabalar WHERE yosh BETWEEN 18 AND 25;
SELECT * FROM talabalar WHERE shahar IN ('Toshkent', 'Samarqand');
SELECT * FROM talabalar WHERE shahar NOT IN ('Toshkent');
findOne() — birinchi topilgan
find() — barcha mos documentlar (cursor qaytaradi).
findOne() — faqat birinchi mos document (object qaytaradi).
db.talabalar.findOne({ ism: "Jasur" })
// → { _id: ObjectId("..."), ism: "Jasur", yosh: 24, ... }
// yoki topilmasa: null
find() → [doc1, doc2, doc3, ...] ← cursor
findOne() → doc1 ← bitta object yoki null
Foydalanish:
// _id bo'yicha — doim findOne yoki find({_id:...})
db.talabalar.findOne({ _id: ObjectId("64a1f2c3b4e5f6a7b8c9d0e1") })
// Birinchi Toshkentlikni topish
db.talabalar.findOne({ shahar: "Toshkent" })
// Topilganini tekshirish
let talaba = db.talabalar.findOne({ ism: "Jasur" })
if (talaba) {
print("Topildi:", talaba.ism)
} else {
print("Topilmadi")
}
Projection — qaysi maydonlar ko'rinsin
Har documentda 20 ta maydon bor, lekin sizga faqat 3 tasi kerak. Projection — ortiqcha maydonlarni filtrlaydi.
Projection qoidasi:
1 → ko'rsat
0 → yashir
Maydonlarni tanlash (inclusion)
db.talabalar.find(
{}, // filter — hammasi
{ ism: 1, yosh: 1, shahar: 1 } // faqat bu uchta
)
Natija:
{ _id: ObjectId("..."), ism: "Jasur", yosh: 24, shahar: "Toshkent" }
{ _id: ObjectId("..."), ism: "Malika", yosh: 22, shahar: "Samarqand" }
_id doim ko'rinadi — maxsus holat. Uni ham yashirish:
db.talabalar.find(
{},
{ ism: 1, yosh: 1, _id: 0 } // ← _id: 0 — yashirish
)
Natija:
{ ism: "Jasur", yosh: 24 }
{ ism: "Malika", yosh: 22 }
Maydonlarni yashirish (exclusion)
// Parol va tokenni yashir, qolganlarni ko'rsat
db.foydalanuvchilar.find(
{},
{ parol: 0, token: 0 }
)
Inclusion va exclusion aralashtirib bo'lmaydi
// ❌ Xato — ikkalasini aralashtirib bo'lmaydi
db.users.find({}, { ism: 1, parol: 0 })
// MongoServerError: Projection cannot have a mix of inclusion
// and exclusion.
// ✅ Istisno: _id ni alohida 0 qilish mumkin
db.users.find({}, { ism: 1, yosh: 1, _id: 0 }) // ← to'g'ri
Ichki maydonlarni projection bilan olish
// Faqat manzil.shahar ni ko'rsat
db.talabalar.find(
{},
{ ism: 1, "manzil.shahar": 1 }
)
// → { ism: "Jasur", manzil: { shahar: "Toshkent" } }
SQL bilan:
-- SQL
SELECT ism, yosh, shahar FROM talabalar;
SELECT ism, yosh FROM talabalar; -- parolsiz
// MongoDB
db.talabalar.find({}, { ism: 1, yosh: 1, shahar: 1 })
db.talabalar.find({}, { parol: 0 })
sort() — tartiblash
db.talabalar.find().sort({ yosh: 1 }) // ↑ kichikdan kattaga (ASC)
db.talabalar.find().sort({ yosh: -1 }) // ↓ kattadan kichikka (DESC)
sort: 1 → A → Z, 1 → 9 (ascending)
sort: -1 → Z → A, 9 → 1 (descending)
Bir nechta maydon bo'yicha sort
// Avval shaharga qarab, keyin yoshga qarab
db.talabalar.find().sort({ shahar: 1, yosh: -1 })
Natija:
{ ism: "Bobur", shahar: "Namangan", yosh: 23 }
{ ism: "Zulfiya",shahar: "Namangan", yosh: 21 }
{ ism: "Malika", shahar: "Samarqand", yosh: 22 }
{ ism: "Jasur", shahar: "Toshkent", yosh: 24 } ← Toshkent: yosh DESC
{ ism: "Sardor", shahar: "Toshkent", yosh: 23 }
SQL bilan:
-- SQL
SELECT * FROM talabalar ORDER BY shahar ASC, yosh DESC;
// MongoDB
db.talabalar.find().sort({ shahar: 1, yosh: -1 })
limit() va skip() — sahifalash
limit() — nechta qaytarsin
db.talabalar.find().limit(5) // faqat 5 ta
db.talabalar.find().limit(10) // faqat 10 ta
skip() — nechtatani o'tkazib yubor
db.talabalar.find().skip(20) // birinchi 20 tani o'tkazib, qolganlarni
Ikkalasi birgalikda — pagination
100 ta document, sahifada 10 tadan:
Sahifa 1: skip(0), limit(10) → 1-10
Sahifa 2: skip(10), limit(10) → 11-20
Sahifa 3: skip(20), limit(10) → 21-30
...
Sahifa N: skip((N-1) * 10), limit(10)
let sahifa = 3
let hajm = 10
db.talabalar
.find()
.sort({ ism: 1 })
.skip((sahifa - 1) * hajm)
.limit(hajm)
SQL bilan:
-- SQL
SELECT * FROM talabalar
ORDER BY ism ASC
LIMIT 10 OFFSET 20; -- 3-sahifa
// MongoDB
db.talabalar.find().sort({ ism: 1 }).skip(20).limit(10)
Zanjir — hammasi birgalikda
find() ga sort(), limit(), skip() va projection zanjir shaklida
ulanadi:
db.talabalar
.find(
{ shahar: "Toshkent" }, // filter
{ ism: 1, yosh: 1, _id: 0 } // projection
)
.sort({ yosh: -1 }) // yoshga qarab kamayib
.skip(0) // 1-sahifa
.limit(10) // 10 tadan
Bajarilish tartibi (ichki):
1. filter → Toshkentliklarni tanlab
2. sort → yoshga qarab tartiblaydi
3. skip → birinchi N tani o'tkazadi
4. limit → M tani qaytaradi
5. project → faqat kerakli maydonlarni qoldirib
SQL bilan to'liq parallel:
SELECT ism, yosh
FROM talabalar
WHERE shahar = 'Toshkent'
ORDER BY yosh DESC
LIMIT 10 OFFSET 0;
countDocuments() — sanaymiz
// Hammasi
db.talabalar.countDocuments()
// Shartli
db.talabalar.countDocuments({ shahar: "Toshkent" })
// ❌ Eski — count() deprecated
db.talabalar.count() // ishlatmang
db.talabalar.find().count() // ishlatmang
SQL bilan:
SELECT COUNT(*) FROM talabalar WHERE shahar = 'Toshkent';
Amaliy misol — to'liq so'rov
E-commerce saytida: aktiv mahsulotlar, narzi arzondan qimmatga, 2-sahifa, faqat nom va narx:
db.mahsulotlar
.find(
{ faol: true, narx: { $gte: 10000 } }, // aktiv, narx >= 10,000
{ nom: 1, narx: 1, _id: 0 } // faqat nom va narx
)
.sort({ narx: 1 }) // arzondan qimmatga
.skip(20) // 2-sahifa (20 tadan)
.limit(20)
Natija:
{ nom: "Daftar", narx: 12000 }
{ nom: "Qalam", narx: 15000 }
{ nom: "Portfel", narx: 85000 }
...
Tez-tez uchraydigan xatolar
find() cursor ni to'g'ridan-to'g'ri ishlatish
let natija = db.talabalar.find({ shahar: "Toshkent" })
// ❌ Bu ishlaydi lekin cursor ob'ekt qaytadi
print(natija) // → MongoCursor {...}
// ✅ Massivga aylantirish
let talabalar = db.talabalar.find({ shahar: "Toshkent" }).toArray()
print(talabalar.length)
Node.js/Mongoose da bu muammo yo'q — await bilan massiv keladi.
projection da 1 va 0 aralashtirish
// ❌ Xato — mix of inclusion and exclusion
db.users.find({}, { ism: 1, parol: 0 })
// ✅ Faqat keraklini tanlash
db.users.find({}, { ism: 1, email: 1, _id: 0 })
// ✅ Yoki faqat kerakmaydiganlarni yashirish
db.users.find({}, { parol: 0, token: 0 })
skip() katta sonlarda sekinlashadi
// ❌ skip(50000) — MongoDB 50,000 documentni skanerlaydi, keyin o'tkazadi
db.loglar.find().skip(50000).limit(10)
Katta collectionlarda skip sekin. Cursor-based pagination yaxshiroq
(bu haqda keyingi bo'limlarda).
sort() index bo'lmasa sekin
// 1,000,000 document bo'lsa va yosh ga index yo'q bo'lsa:
db.talabalar.find().sort({ yosh: 1 })
// → butun collectionni scan qiladi, keyin sort — juda sekin
Tez-tez sort qiladiganingizga index qo'ying (26-darsda batafsil).
Xulosa
┌─────────────────────────────────────────────────────────────────┐
│ find(<filter>, <projection>) │
│ ↓ ↓ │
│ { field: val } { field: 1/0 } │
│ $gt, $lt, $in... 1=ko'rsat, 0=yashir │
├─────────────────────────────────────────────────────────────────┤
│ .sort({ field: 1/-1 }) → 1=ASC, -1=DESC │
│ .limit(N) → N ta qaytaradi │
│ .skip(N) → N tani o'tkazib yuboradi │
│ .countDocuments() → soni │
├─────────────────────────────────────────────────────────────────┤
│ findOne() → bitta object yoki null │
│ find() → cursor (barcha mos documentlar) │
└─────────────────────────────────────────────────────────────────┘
find({})— barchasi; filter bersangiz — mos kelganlar- Projection:
{ a: 1, b: 1 }yoki{ c: 0 }— aralashtirib bo'lmaydi - Zanjir:
.sort().skip().limit()— ketma-ket ulanadi - Pagination:
skip((page-1) * size).limit(size)
Keyingi dars: 8-dars — Query operatorlari: $eq, $gt, $lt, $in, $nin, $exists, $regex