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.

🕑 11 daqiqa o‘qish 📄 697 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. LIKE nima uchun yetmaydi
  2. tsvector va tsquery
  3. Qidiruv so'rovi
  4. So'rov turlari
  5. Natijani saralash
  6. Tezlashtirish
  7. Xulosa

Matn ichidan qidirish - deyarli har bir loyihada uchraydigan vazifa. LIKE bilan boshlanadi, lekin tez orada yetmay qoladi.

SQL
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 #

SQL
SELECT sarlavha FROM maqola WHERE matn LIKE '%quer%' ORDER BY id;
Natija
        sarlavha
------------------------
 PostgreSQL indexes
 Database design basics
 Writing fast queries
(3 rows)

LIKE ishladi, lekin uning uchta jiddiy kamchiligi bor:

MuammoMisol
So'z shakllarini bilmaydiquery va queries - alohida
TartibsizQaysi natija muhimroq - noma'lum
Sekin% bilan boshlansa, indeks ishlamaydi

tsvector va tsquery #

To'liq matn qidiruv matnni leksemalarga - normallashtirilgan so'z o'zaklariga ajratadi:

SQL
SELECT to_tsvector('english',
                   'The indexes and the queries are faster') AS leksemalar;
Natija
           leksemalar
--------------------------------
 'faster':7 'index':2 'queri':5
(1 row)

Ikkita narsa sodir bo'ldi.

Birinchidan, so'zlar o'zagiga keltirildi: indexesindex, queriesqueri.

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:

SQL
SELECT plainto_tsquery('english', 'fast queries') AS sorov,
       to_tsvector('english', 'Writing fast queries') @@
       plainto_tsquery('english', 'fast queries') AS mos_keldimi;
Natija
      sorov       | mos_keldimi
------------------+-------------
 'fast' & 'queri' | t
(1 row)

@@ operatori - "shu matn shu so'rovga mos keladimi" degani.

Matn ham, so'rov ham bir xil ishlov ko'radi "The indexes and the queries are faster" "fast queries" to_tsvector plainto_tsquery 'faster':7 'index':2 'queri':5 the, and, are - to'xtash so'zlari 'fast' & 'queri' ikkalasi ham bo'lishi shart @@ Ikkala tomon bir xil qoidada normallashtirilgani uchun "queries" va "query" mos keladi Muhim: ikkala tomonda ham BIR XIL konfiguratsiya ishlatilishi shart
Qidiruv matnni emas, uning o'zaklarini solishtiradi

Qidiruv so'rovi #

SQL
SELECT sarlavha
FROM maqola
WHERE to_tsvector('english', sarlavha || ' ' || matn)
      @@ plainto_tsquery('english', 'slow queries')
ORDER BY id;
Natija
        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:

FunksiyaKirishIshlatilishi
to_tsqueryQat'iy sintaksis: fast & queriDastur yozgan so'rov
plainto_tsqueryOddiy matn, hammasi ANDSodda qidiruv
websearch_to_tsquery"ibora", -istisno, orFoydalanuvchi qidiruvi
SQL
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;
Natija
      istisno       |       ibora        |        yoki
--------------------+--------------------+--------------------
 'data' & !'backup' | 'slow' <-> 'queri' | 'index' | 'backup'
(1 row)
Foydalanuvchi kiritgan matn uchun websearch_to_tsquery

to_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 yozadiMa'nosi
tez so'rovikkala so'z ham bo'lsin
"tez so'rov"aynan shu ibora
so'rov -sekinsekin bo'lmasin
indeks or zaxirabittasi yetarli

Qidiruv oynasi uchun deyarli har doim shu tanlanadi.

Natijani saralash #

Qidiruvning yarmi - topish, ikkinchi yarmi - muhimini yuqoriga chiqarish:

SQL
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;
Natija
        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:

UsulIzoh
Hisoblanadigan ustun + GIN indeksEng tez, joy talab qiladi
Ifoda ustidan GIN indeksUstun qo'shmaydi
SQL
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;
Natija
ALTER TABLE
CREATE INDEX
     sarlavha
-------------------
 Backup strategies
(1 row)

Endi to_tsvector faqat yozishda hisoblanadi va GIN indeks qidiruvni tezlashtiradi (14-bo'limda batafsil).

O'zbek tili uchun tayyor konfiguratsiya yo'q

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.

KonfiguratsiyaO'zbekcha matnda
simpleFaqat kichik harfga o'tkazadi va bo'ladi
englishNoto'g'ri - ingliz qoidalarini qo'llaydi

Amaliy yechimlar:

  1. simple + unaccent - eng sodda yo'l, qo'shimchalarni ajratmaydi.
  2. pg_trgm kengaytmasi - uch harfli bo'laklar bo'yicha o'xshashlik qidiradi; qo'shimchalarga sezgir emas.
  3. O'z lug'atingiz - synonym yoki thesaurus fayli bilan eng ko'p uchraydigan shakllarni bog'lash.

Ko'p o'zbekcha loyihalarda ikkinchi usul - pg_trgm - amalda eng yaxshi natija beradi.

Amaliy topshiriq
  1. LIKE bilan qidiruv yozing va uning uchta kamchiligini sanang.
  2. to_tsvector natijasini ko'ring - qaysi so'zlar yo'qoldi?
  3. Nima uchun ular yo'qolganini yozing.
  4. queries so'rovi query so'zini topa oladimi? Tekshiring.
  5. plainto_tsquery va websearch_to_tsquery farqini sinang.
  6. -so'z bilan istisno qidiruv yozing.
  7. "ibora" bilan aniq ibora qidiring.
  8. ts_rank bilan natijani saralang.
  9. Hisoblanadigan tsvector ustuni qo'shing va GIN indeks yarating.
  10. O'zbek tili uchun qaysi yechimni tanlagan bo'lardingiz? Asoslang.

Xulosa #

  • LIKE so'z shakllarini bilmaydi, natijani saralamaydi va % bilan boshlansa sekin.
  • To'liq matn qidiruv matnni leksemalarga ajratadi va to'xtash so'zlarini tashlaydi.
  • to_tsvector matnni, *_tsquery esa so'rovni normallashtiradi.
  • @@ operatori ularni solishtiradi.
  • Ikkala tomonda bir xil konfiguratsiya ishlatilishi shart.
  • websearch_to_tsquery foydalanuvchi kiritgan matn uchun eng xavfsiz - u xato bermaydi.
  • U "ibora", -istisno va or sintaksisini tushunadi.
  • ts_rank natijani muhimlik bo'yicha saralaydi.
  • Tezlik uchun tsvector ni hisoblanadigan ustunda saqlab, GIN indeks qo'ying.
  • O'zbek tili uchun tayyor konfiguratsiya yo'q - amalda ko'pincha pg_trgm ishlatiladi.

Keyingi bo'limda indekslarni batafsil 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.