Atlas Search — full-text search, fuzzy, autocomplete
Muammodan boshlaylik
Do'kon qidiruvi $text (30-dars) bilan ishlaydi. Foydalanuvchilar shikoyat qiladi:
- "samsnug" yozdim — hech narsa chiqmadi (xato yozilgan so'z)
- "sams" yozayotganimda takliflar chiqmaydi (autocomplete yo'q)
- "telefonlar" deb qidirsam, "telefon" nomli mahsulotlar topilmaydi (o'zbek tilidagi qo'shimchalar)
- Natijalar orasida eng mosi qaysi — tartib noaniq
Alohida Elasticsearch o'rnatish — yana bir tizim, sinxronlash, monitoring.
Atlas Search nima?
Atlas Search — Atlas cluster ichiga o'rnatilgan, Apache Lucene asosidagi to'liq matnli qidiruv. Elasticsearch ni ham shu Lucene harakatlantiradi.
- Ma'lumotlar avtomatik sinxronlanadi — alohida tizim yo'q
- Aggregation pipeline dagi
$searchbosqichi orqali ishlatiladi - Fuzzy, autocomplete, sinonimlar, ajratib ko'rsatish (highlight), facet lar
$text |
Atlas Search | |
|---|---|---|
| Xato yozilgan so'z | ❌ | ✅ fuzzy |
| Autocomplete | ❌ | ✅ |
| Reyting sozlash | Cheklangan | To'liq (boost, function score) |
| Analizatorlar | Bir nechta til | Ko'p tillar, o'z analizatorlaringiz |
| Qayerda | Har qanday MongoDB | Atlas (va yangi versiyalarda lokal Community/Enterprise ham) |
Hayotiy o'xshatma
Tajribali kutubxonachi. Siz "Qodiriyning o'tkir kunlari" desangiz — u xatoni tushunib, "O'tkan kunlar"ni beradi (fuzzy). "O'tk..." deyishingiz bilan — "O'tkan kunlarmi?" deb so'raydi (autocomplete). Va sizga eng mos kitobni birinchi qo'yadi.
Search index yaratish
Atlas → Database → cluster → Atlas Search → Create Search Index → JSON Editor:
{
"mappings": {
"dynamic": false,
"fields": {
"nomi": [
{ "type": "string", "analyzer": "lucene.standard" },
{ "type": "autocomplete", "tokenization": "edgeGram", "minGrams": 2, "maxGrams": 15 }
],
"tavsif": { "type": "string" },
"brend": { "type": "string" },
"kategoriya": { "type": "token" },
"narx": { "type": "number" }
}
}
}
Index nomi: mahsulotlar_search, collection: mahsulotlar.
dynamic: false— faqat ko'rsatilgan maydonlar indekslanadi (kichik va tez index)string— so'zlarga ajratilgan matn qidiruviautocomplete— so'z boshlari bo'yichatoken— aniq qiymat bo'yicha filtr va facet uchun
Yoki koddan:
await Mahsulot.collection.createSearchIndex({ name: 'mahsulotlar_search', definition: { mappings: { ... } } })
Oddiy qidiruv
const natija = await Mahsulot.aggregate([
{ $search: {
index: 'mahsulotlar_search',
text: {
query: req.query.q,
path: ['nomi', 'tavsif', 'brend'],
},
} },
{ $limit: 20 },
{ $project: { nomi: 1, narx: 1, rasm: 1, ball: { $meta: 'searchScore' } } },
])
$search — pipeline ning birinchi bosqichi bo'lishi shart. Natijalar avtomatik moslik bo'yicha tartiblanadi.
Fuzzy — xatolarga chidamli
{ $search: {
index: 'mahsulotlar_search',
text: {
query: 'samsnug galaxi',
path: ['nomi', 'brend'],
fuzzy: { maxEdits: 1, prefixLength: 2 },
},
} }
maxEdits— nechta harf farqi kechiriladi (1 yoki 2)prefixLength— so'zning birinchi nechta harfi aniq bo'lishi kerak (tezlik va aniqlik uchun)
"samsnug" → "Samsung" ✅
Autocomplete
router.get('/takliflar', async (req, res) => {
const q = String(req.query.q ?? '').trim()
if (q.length < 2) return res.json([])
const takliflar = await Mahsulot.aggregate([
{ $search: {
index: 'mahsulotlar_search',
autocomplete: {
query: q,
path: 'nomi',
fuzzy: { maxEdits: 1, prefixLength: 1 },
},
} },
{ $limit: 8 },
{ $project: { _id: 1, nomi: 1 } },
])
res.json(takliflar)
})
Frontend da debounce (JS kursi, 83-dars) bilan har 300 ms da so'rov.
Murakkab so'rov — compound
{ $search: {
index: 'mahsulotlar_search',
compound: {
must: [
{ text: { query: req.query.q, path: ['nomi', 'tavsif'], fuzzy: { maxEdits: 1 } } },
],
should: [
{ text: { query: req.query.q, path: 'nomi', score: { boost: { value: 3 } } } },
],
filter: [
{ equals: { path: 'kategoriya', value: 'telefon' } },
{ range: { path: 'narx', gte: 1000000, lte: 5000000 } },
],
},
} }
| Bo'lim | Ma'nosi |
|---|---|
must |
Albatta mos bo'lsin, ballga ta'sir qiladi |
should |
Mos bo'lsa — ball oshadi (nomida bo'lsa — 3 barobar) |
filter |
Albatta mos bo'lsin, ballga ta'sir qilmaydi |
mustNot |
Mos bo'lmasin |
Highlight — mos qismni ajratish
[
{ $search: {
index: 'mahsulotlar_search',
text: { query: 'simsiz quloqchin', path: 'tavsif' },
highlight: { path: 'tavsif' },
} },
{ $project: { nomi: 1, ajratilgan: { $meta: 'searchHighlights' } } },
]
Natijada tavsifning qaysi qismlari mos kelgani — frontend da <mark> bilan ko'rsatish uchun.
[!INFO] O'zbek tili uchun Atlas Search da maxsus analizator yo'q.
lucene.standardso'zlarni to'g'ri ajratadi, lekin "telefonlar" va "telefon" ni bitta so'z deb bilmaydi. Yechimlar:autocomplete(edgeGram) so'z boshlari bo'yicha topadi; sinonimlar collection i bilan muhim shakllarni bog'lash; yoki custom analizator.
Tez-tez uchraydigan xatolar
$search ni birinchi bosqich qilmaslik
$match dan keyin $search — xato. Filtrlarni compound.filter ga qo'ying.
Index nomini ko'rsatmaslik
index ko'rsatilmasa — default nomli index qidiriladi. Topilmasa — natija jim bo'sh.
Har bir harf bosilganda so'rov
Autocomplete — debounce va minimal uzunlik (2 harf) bilan.
Xulosa
- Atlas Search — Lucene asosidagi qidiruv, cluster ichida, avtomatik sinxron
- Search index:
string,autocomplete,token,number;dynamic: false $search— pipeline ning birinchi bosqichi;searchScore— moslik bahosifuzzy— xato yozilgan so'zlar;autocomplete— takliflarcompound:must,should(boost),filter,mustNothighlight— mos qismlarni ajratish; o'zbek tili — autocomplete va sinonimlar
Keyingi dars: 54-dars — Atlas Triggers va Functions — serverless logika