13-bo‘lim
To'liq matn qidiruv
LIKE ning cheklovlari, tsvector va tsquery, to_tsvector va websearch_to_tsquery, natijani saralash va o'zbek tili uchun holat.
Ushbu bo‘lim mundarijasi
Matn ichidan qidirish - deyarli har bir loyihada uchraydigan
vazifa. LIKE bilan boshlanadi, lekin tez orada yetmay
qoladi.
CREATE TABLE maqola (
id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
sarlavha text NOT NULL,
matn text NOT NULL
);
INSERT INTO maqola (sarlavha, matn) VALUES
('PostgreSQL indexes',
'Indexes make queries faster but slow down writing data'),
('Database design basics',
'Good design prevents slow queries and broken data later'),
('Writing fast queries',
'A slow query is often caused by a missing index'),
('Backup strategies',
'Regular backups protect data from hardware failure');
LIKE nima uchun yetmaydi #
SELECT sarlavha FROM maqola WHERE matn LIKE '%quer%' ORDER BY id;
sarlavha
------------------------
PostgreSQL indexes
Database design basics
Writing fast queries
(3 rows)
LIKE ishladi, lekin uning uchta jiddiy kamchiligi bor:
| Muammo | Misol |
|---|---|
| So'z shakllarini bilmaydi | query va queries - alohida |
| Tartibsiz | Qaysi natija muhimroq - noma'lum |
| Sekin | % bilan boshlansa, indeks ishlamaydi |
tsvector va tsquery #
To'liq matn qidiruv matnni leksemalarga - normallashtirilgan so'z o'zaklariga ajratadi:
SELECT to_tsvector('english',
'The indexes and the queries are faster') AS leksemalar;
leksemalar
--------------------------------
'faster':7 'index':2 'queri':5
(1 row)
Ikkita narsa sodir bo'ldi.
Birinchidan, so'zlar o'zagiga keltirildi: indexes →
index, queries → queri.
Ikkinchidan, the, and va are umuman yo'qoldi - ular
to'xtash so'zlari (stop words). Ular deyarli har
matnda uchraydi, shuning uchun qidiruvda foydasi yo'q.
Raqamlarga qarang: 2, 5, 7. Ular so'zning asl
matndagi o'rni - oraliqdagi raqamlar tashlangan so'zlarga
tegishli. Bu raqamlar keyinroq saralashda ishga tushadi.
So'rov tomoni ham shunday normallashtiriladi:
SELECT plainto_tsquery('english', 'fast queries') AS sorov,
to_tsvector('english', 'Writing fast queries') @@
plainto_tsquery('english', 'fast queries') AS mos_keldimi;
sorov | mos_keldimi
------------------+-------------
'fast' & 'queri' | t
(1 row)
@@ operatori - "shu matn shu so'rovga mos keladimi" degani.
Qidiruv so'rovi #
SELECT sarlavha
FROM maqola
WHERE to_tsvector('english', sarlavha || ' ' || matn)
@@ plainto_tsquery('english', 'slow queries')
ORDER BY id;
sarlavha
------------------------
PostgreSQL indexes
Database design basics
Writing fast queries
(3 rows)
LIKE topa olmagan narsani u topdi: queries so'rovi
query so'zini ham qamrab oldi.
So'rov turlari #
Uchta funksiya bor va ular turlicha ishlaydi:
| Funksiya | Kirish | Ishlatilishi |
|---|---|---|
to_tsquery | Qat'iy sintaksis: fast & queri | Dastur yozgan so'rov |
plainto_tsquery | Oddiy matn, hammasi AND | Sodda qidiruv |
websearch_to_tsquery | "ibora", -istisno, or | Foydalanuvchi qidiruvi |
SELECT websearch_to_tsquery('english', 'data -backup') AS istisno,
websearch_to_tsquery('english', '"slow query"') AS ibora,
websearch_to_tsquery('english', 'index or backup') AS yoki;
istisno | ibora | yoki
--------------------+--------------------+--------------------
'data' & !'backup' | 'slow' <-> 'queri' | 'index' | 'backup'
(1 row)
websearch_to_tsqueryto_tsquery qat'iy sintaksis kutadi. Foydalanuvchi tasodifan
& yoki ( yozsa, so'rov xato bilan yiqiladi.
websearch_to_tsquery esa hech qachon xato bermaydi - u
tushunmagan belgilarni shunchaki tashlab yuboradi.
Ustiga-ustak u odamlarga tanish sintaksisni tushunadi:
| Foydalanuvchi yozadi | Ma'nosi |
|---|---|
tez so'rov | ikkala so'z ham bo'lsin |
"tez so'rov" | aynan shu ibora |
so'rov -sekin | sekin bo'lmasin |
indeks or zaxira | bittasi yetarli |
Qidiruv oynasi uchun deyarli har doim shu tanlanadi.
Natijani saralash #
Qidiruvning yarmi - topish, ikkinchi yarmi - muhimini yuqoriga chiqarish:
SELECT sarlavha,
round(ts_rank(
to_tsvector('english', sarlavha || ' ' || matn),
plainto_tsquery('english', 'slow query')
)::numeric, 4) AS reyting
FROM maqola
WHERE to_tsvector('english', sarlavha || ' ' || matn)
@@ plainto_tsquery('english', 'slow query')
ORDER BY reyting DESC;
sarlavha | reyting
------------------------+---------
Writing fast queries | 0.1878
Database design basics | 0.0991
PostgreSQL indexes | 0.0974
(3 rows)
ts_rank so'z chastotasi va o'rniga qarab baho beradi.
Sarlavhani muhimroq qilish uchun og'irlik berish mumkin -
setweight funksiyasi bilan.
Tezlashtirish #
Har so'rovda to_tsvector ni qayta hisoblash sekin. Ikki
yechim bor:
| Usul | Izoh |
|---|---|
| Hisoblanadigan ustun + GIN indeks | Eng tez, joy talab qiladi |
| Ifoda ustidan GIN indeks | Ustun qo'shmaydi |
ALTER TABLE maqola
ADD COLUMN qidiruv tsvector
GENERATED ALWAYS AS (
to_tsvector('english', sarlavha || ' ' || matn)
) STORED;
CREATE INDEX maqola_qidiruv_idx ON maqola USING GIN (qidiruv);
SELECT sarlavha FROM maqola
WHERE qidiruv @@ websearch_to_tsquery('english', 'backup')
ORDER BY id;
ALTER TABLE
CREATE INDEX
sarlavha
-------------------
Backup strategies
(1 row)
Endi to_tsvector faqat yozishda hisoblanadi va GIN
indeks qidiruvni tezlashtiradi (14-bo'limda batafsil).
PostgreSQL 30 ga yaqin til uchun so'z o'zaklarini ajratishni biladi: ingliz, rus, turk, arab va boshqalar.
O'zbek tili ular orasida yo'q.
Bu quyidagini anglatadi: simple konfiguratsiyasida
kitoblar, kitobi va kitoblarni uchta har xil so'z
sifatida qaraladi.
| Konfiguratsiya | O'zbekcha matnda |
|---|---|
simple | Faqat kichik harfga o'tkazadi va bo'ladi |
english | Noto'g'ri - ingliz qoidalarini qo'llaydi |
Amaliy yechimlar:
simple+unaccent- eng sodda yo'l, qo'shimchalarni ajratmaydi.pg_trgmkengaytmasi - uch harfli bo'laklar bo'yicha o'xshashlik qidiradi; qo'shimchalarga sezgir emas.- O'z lug'atingiz -
synonymyokithesaurusfayli bilan eng ko'p uchraydigan shakllarni bog'lash.
Ko'p o'zbekcha loyihalarda ikkinchi usul - pg_trgm - amalda
eng yaxshi natija beradi.
LIKEbilan qidiruv yozing va uning uchta kamchiligini sanang.to_tsvectornatijasini ko'ring - qaysi so'zlar yo'qoldi?- Nima uchun ular yo'qolganini yozing.
queriesso'roviqueryso'zini topa oladimi? Tekshiring.plainto_tsqueryvawebsearch_to_tsqueryfarqini sinang.-so'zbilan istisno qidiruv yozing."ibora"bilan aniq ibora qidiring.ts_rankbilan natijani saralang.- Hisoblanadigan
tsvectorustuni qo'shing va GIN indeks yarating. - O'zbek tili uchun qaysi yechimni tanlagan bo'lardingiz? Asoslang.
Xulosa #
LIKEso'z shakllarini bilmaydi, natijani saralamaydi va%bilan boshlansa sekin.- To'liq matn qidiruv matnni leksemalarga ajratadi va to'xtash so'zlarini tashlaydi.
to_tsvectormatnni,*_tsqueryesa so'rovni normallashtiradi.@@operatori ularni solishtiradi.- Ikkala tomonda bir xil konfiguratsiya ishlatilishi shart.
websearch_to_tsqueryfoydalanuvchi kiritgan matn uchun eng xavfsiz - u xato bermaydi.- U
"ibora",-istisnovaorsintaksisini tushunadi. ts_ranknatijani muhimlik bo'yicha saralaydi.- Tezlik uchun
tsvectorni hisoblanadigan ustunda saqlab, GIN indeks qo'ying. - O'zbek tili uchun tayyor konfiguratsiya yo'q - amalda ko'pincha
pg_trgmishlatiladi.
Keyingi bo'limda indekslarni batafsil ko'ramiz.
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.