5-bo‘lim

So'rovlar va filtr operatorlari

find filtri, solishtirish operatorlari, $in va $nin, $and va $or, $exists va $type, $regex hamda proyeksiya bilan maydon tanlash.

🕑 16 daqiqa o‘qish 📄 808 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Eng oddiy filtr
  2. Solishtirish operatorlari
  3. $or va $and
  4. $exists va $type
  5. Matn bo'yicha qidirish
  6. Proyeksiya - qaysi maydonlar qaytadi
  7. Sanash
  8. Xulosa

find ikkita argument oladi: nimani topish va qaysi maydonlarni qaytarish. Bu bobda ikkalasini ham to'liq ko'rib chiqamiz.

JavaScript
db.kitob.insertMany([
  { _id: 1, nom: "Otkan kunlar",     muallif: "Abdulla Qodiriy",
    yil: 1926, narx: 85000, nusxa: 12, janr: "tarixiy" },
  { _id: 2, nom: "Mehrobdan chayon", muallif: "Abdulla Qodiriy",
    yil: 1929, narx: 72000, nusxa: 5,  janr: "tarixiy" },
  { _id: 3, nom: "Kecha va kunduz",  muallif: "Cho'lpon",
    yil: 1936, narx: 68000, nusxa: 0,  janr: "ijtimoiy" },
  { _id: 4, nom: "Navoiy",           muallif: "Oybek",
    yil: 1944, narx: 95000, nusxa: 8,  janr: "tarixiy" },
  { _id: 5, nom: "Ufq",              muallif: "Said Ahmad",
    yil: 1964, narx: 64000, nusxa: 21, janr: "zamonaviy" },
  { _id: 6, nom: "Sarob",            muallif: "Abdulla Qahhor",
    yil: 1935, narx: 59000, janr: "ijtimoiy" }
])

Eng oddiy filtr #

Filtr - bu oddiy hujjat. Undagi har bir maydon shart bo'lib xizmat qiladi:

JavaScript
db.kitob.find({ janr: "tarixiy" }, { nom: 1, yil: 1 })
Natija
[
  { _id: 1, nom: 'Otkan kunlar', yil: 1926 },
  { _id: 2, nom: 'Mehrobdan chayon', yil: 1929 },
  { _id: 4, nom: 'Navoiy', yil: 1944 }
]

Bir nechta maydon yozilsa, ular VA bilan bog'lanadi:

JavaScript
db.kitob.find({ janr: "tarixiy", muallif: "Abdulla Qodiriy" }, { nom: 1 })
Natija
[
  { _id: 1, nom: 'Otkan kunlar' },
  { _id: 2, nom: 'Mehrobdan chayon' }
]

Solishtirish operatorlari #

OperatorMa'nosi
$eqTeng (odatiy - yozish shart emas)
$neTeng emas
$gtKatta
$gteKatta yoki teng
$ltKichik
$lteKichik yoki teng
$inRo'yxatdagilardan biri
$ninRo'yxatda yo'q
JavaScript
db.kitob.find(
  { yil: { $gte: 1930, $lt: 1950 } },
  { nom: 1, yil: 1 }
)
Natija
[
  { _id: 3, nom: 'Kecha va kunduz', yil: 1936 },
  { _id: 4, nom: 'Navoiy', yil: 1944 },
  { _id: 6, nom: 'Sarob', yil: 1935 }
]

Bitta maydonga ikkita shart yozilgani e'tiborga loyiq - ular ham VA bilan bog'lanadi.

JavaScript
db.kitob.find(
  { janr: { $in: ["ijtimoiy", "zamonaviy"] } },
  { nom: 1, janr: 1 }
)
Natija
[
  { _id: 3, nom: 'Kecha va kunduz', janr: 'ijtimoiy' },
  { _id: 5, nom: 'Ufq', janr: 'zamonaviy' },
  { _id: 6, nom: 'Sarob', janr: 'ijtimoiy' }
]

$or va $and #

JavaScript
db.kitob.find(
  { $or: [ { narx: { $lt: 60000 } }, { nusxa: { $gt: 20 } } ] },
  { nom: 1, narx: 1, nusxa: 1 }
)
Natija
[
  { _id: 5, nom: 'Ufq', narx: 64000, nusxa: 21 },
  { _id: 6, nom: 'Sarob', narx: 59000 }
]
$and deyarli hech qachon kerak emas

Chunki filtrdagi maydonlar allaqachon VA bilan bog'lanadi:

YozuvBir xilmi
{ janr: "tarixiy", yil: 1926 }Ha
{ $and: [{ janr: "tarixiy" }, { yil: 1926 }] }Ha - lekin uzunroq

$and faqat bitta holatda haqiqatan kerak bo'ladi: bir xil maydonga bir xil operatorni ikki marta qo'llash zarur bo'lganda.

Masalan "narxi 60 000 dan katta VA 90 000 dan kichik" ni oddiy yozib bo'ladi:

Natija
{ narx: { $gt: 60000, $lt: 90000 } }

Lekin "ikki xil $or sharti birga bajarilsin" ni yozish uchun $and kerak, chunki hujjatda bitta kalit ikki marta bo'la olmaydi.

$exists va $type #

Oltinchi kitobda nusxa maydoni yo'q:

JavaScript
db.kitob.find({ nusxa: { $exists: false } }, { nom: 1 })
db.kitob.countDocuments({ nusxa: { $exists: true } })
Natija
[ { _id: 6, nom: 'Sarob' } ]
5
$ne va $nin maydoni yo'q hujjatlarni ham oladi

Bu eng ko'p zarar keltiradigan tuzoqlardan biri.

{ nusxa: { $ne: 0 } } shartini "nusxasi bor kitoblar" deb o'ylash tabiiy. Lekin MongoDB uni shunday tushunadi:

nusxa qiymati 0 ga teng bo'lmagan hujjatlar - shu jumladan nusxa umuman yo'q bo'lganlar

Chunki "mavjud bo'lmagan maydon" ham 0 ga teng emas.

To'g'ri yozuv ikkita shartdan iborat:

Natija
{ nusxa: { $exists: true, $ne: 0 } }

Yoki muammoni butunlay yo'qotish uchun sxemani qat'iy qiling: maydon har doim bo'lsin va bo'sh holat 0 bilan yozilsin. 11-bobda buni $jsonSchema bilan qanday majburlashni ko'ramiz.

Quyidagi ikki so'rov farqini solishtiring:

JavaScript
db.kitob.find({ nusxa: { $ne: 0 } }, { nom: 1, nusxa: 1 })
Natija
[
  { _id: 1, nom: 'Otkan kunlar', nusxa: 12 },
  { _id: 2, nom: 'Mehrobdan chayon', nusxa: 5 },
  { _id: 4, nom: 'Navoiy', nusxa: 8 },
  { _id: 5, nom: 'Ufq', nusxa: 21 },
  { _id: 6, nom: 'Sarob' }
]
JavaScript
db.kitob.find({ nusxa: { $exists: true, $ne: 0 } }, { nom: 1, nusxa: 1 })
Natija
[
  { _id: 1, nom: 'Otkan kunlar', nusxa: 12 },
  { _id: 2, nom: 'Mehrobdan chayon', nusxa: 5 },
  { _id: 4, nom: 'Navoiy', nusxa: 8 },
  { _id: 5, nom: 'Ufq', nusxa: 21 }
]

Birinchisiga Sarob ham tushdi - garchi uning nusxa maydoni umuman yo'q bo'lsa ham.

Matn bo'yicha qidirish #

JavaScript
db.kitob.find({ nom: { $regex: /kun/i } }, { nom: 1 })
Natija
[ { _id: 1, nom: 'Otkan kunlar' }, { _id: 3, nom: 'Kecha va kunduz' } ]
YozuvMa'nosi
/kun/Ichida "kun" bo'lsa
/^kun/"kun" bilan boshlansa
/kun$/"kun" bilan tugasa
/kun/iKatta-kichik harfga e'tiborsiz
$regex indeksdan deyarli foydalanmaydi

Faqat bitta holat tezkor: ifoda ^ bilan boshlanadigan va registrga sezgir bo'lsa.

IfodaIndeks ishlaydimi
/^Otkan/Ha - prefiks bo'yicha
/^Otkan/iYo'q - i bayrog'i buzadi
/kunlar/Yo'q - butun to'plam o'qiladi
/kunlar$/Yo'q

Sabab oddiy: B-tree indeks qiymatlarni boshidan tartiblangan holda saqlaydi. "Boshi ma'lum" bo'lsa, u kerakli joyga sakrab boradi. "Ichida bor" degan savolga esa javob berish uchun hamma qiymatni ko'rish kerak.

Haqiqiy matn qidiruvi uchun matn indeksi yoki $text ishlatiladi - 15-bobda ko'ramiz.

Proyeksiya - qaysi maydonlar qaytadi #

Ikkinchi argument proyeksiya deb ataladi:

JavaScript
db.kitob.findOne({ _id: 1 }, { nom: 1, narx: 1 })
db.kitob.findOne({ _id: 1 }, { nom: 1, narx: 1, _id: 0 })
db.kitob.findOne({ _id: 1 }, { nusxa: 0, janr: 0, yil: 0 })
Natija
{ _id: 1, nom: 'Otkan kunlar', narx: 85000 }
{ nom: 'Otkan kunlar', narx: 85000 }
{
  _id: 1,
  nom: 'Otkan kunlar',
  muallif: 'Abdulla Qodiriy',
  narx: 85000
}

Uchta qoida:

YozuvNatija
{ nom: 1 }Faqat nom (va _id)
{ nom: 1, _id: 0 }Faqat nom
{ nusxa: 0 }nusxa dan boshqa hammasi
_id - yagona istisno

Proyeksiyada 1 va 0 ni aralashtirib bo'lmaydi:

Natija
db.kitob.find({}, { nom: 1, narx: 0 })

MongoServerError[Location31254]: Cannot do exclusion on
field narx in inclusion projection

Ya'ni yo "faqat shularni ber", yo "shulardan boshqa hammasini ber" - o'rtasi yo'q.

Yagona istisno - _id. U odatiy holda har doim qaytadi, shuning uchun uni alohida o'chirish mumkin: { nom: 1, _id: 0 } to'g'ri yozuv.

Proyeksiya shunchaki qulaylik emas - u tarmoq orqali uzatiladigan hajmni ham kamaytiradi. Katta hujjatlarda bu sezilarli farq beradi.

find() ikkita savolga javob beradi 1. Filtr: qaysi hujjatlar? { janr: "tarixiy" } Qatorlarni tanlaydi SQL dagi WHERE ga o'xshaydi 2. Proyeksiya: qaysi maydonlar? { nom: 1, narx: 1, _id: 0 } Ustunlarni tanlaydi SQL dagi SELECT ro'yxatiga o'xshaydi SQL bilan solishtirish SELECT nom, narx FROM kitob WHERE janr = 'tarixiy' db.kitob.find({ janr: "tarixiy" }, { nom: 1, narx: 1, _id: 0 })
Filtr qatorni, proyeksiya esa maydonni kamaytiradi

Sanash #

JavaScript
db.kitob.countDocuments()
db.kitob.countDocuments({ janr: "tarixiy" })
db.kitob.distinct("janr")
db.kitob.distinct("muallif", { janr: "tarixiy" })
Natija
6
3
[ 'ijtimoiy', 'tarixiy', 'zamonaviy' ]
[ 'Abdulla Qodiriy', 'Oybek' ]

distinct - takrorlanmagan qiymatlar ro'yxati. SQL dagi SELECT DISTINCT ning muqobili.

Amaliy topshiriq
  1. Bitta maydon bo'yicha oddiy filtr yozing.
  2. Ikkita shartli filtr yozing va ular qanday bog'langanini ayting.
  3. $gte va $lt bilan oraliq so'rov tuzing.
  4. $in bilan ikkita janrni filtrlang.
  5. $or bilan ikki xil shartdan birini qanoatlantiruvchilarni toping.
  6. $and qachon haqiqatan kerakligini yozing.
  7. $ne filtri nega maydoni yo'q hujjatlarni ham olishini tushuntiring.
  8. Uni $exists bilan to'g'rilang.
  9. $regex qaysi holatda indeksdan foydalanishini yozing.
  10. _id ni chiqarmaydigan proyeksiya yozing.

Xulosa #

  • Filtr - oddiy hujjat; undagi maydonlar VA bilan bog'lanadi.
  • Bitta maydonga bir nechta shart yozish mumkin: { yil: { $gte: 1930, $lt: 1950 } }.
  • $in ro'yxatdan birini, $nin ro'yxatda yo'qini tanlaydi.
  • $or massiv oladi; $and deyarli hech qachon kerak emas.
  • $ne va $nin maydoni yo'q hujjatlarni ham qamrab oladi.
  • To'g'ri yozuv: { maydon: { $exists: true, $ne: qiymat } }.
  • $regex faqat ^ bilan boshlanadigan, registrga sezgir ifodada indeksdan foydalanadi.
  • Proyeksiyada 1 va 0 ni aralashtirib bo'lmaydi - _id dan boshqa.
  • Proyeksiya tarmoq orqali uzatiladigan hajmni ham kamaytiradi.
  • distinct takrorlanmagan qiymatlar ro'yxatini beradi.

Keyingi bo'limda massiv va ichma-ich hujjatlar ichidan qidirishni ko'ramiz.

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.