Əsas məzmuna keçin

PostgreSQL Full-Text Search (FTS)

  • Built-in Axtarış: PostgreSQL-də daxili tam mətn axtarışı (Full-Text Search) dəstəyi.
  • Dil Dəstəyi: Müxtəlif dillər üçün text search konfiqurasiyaları.
  • Ranking: Axtarış nəticələrini relevantlığa görə sıralama.
  • Performance: GIN və GiST indeksləri ilə sürətli axtarış.
  • Fuzzy Search: Similarity və trigram axtarış dəstəyi.
  • Highlight: Axtarış nəticələrində uyğun gələn hissələri vurğulama.
  • Weighted Search: Müxtəlif field-lərə çəki verib axtarış etmək.
  • Phrase Search: Dəqiq ifadə axtarışı.

Əsas Konseptlər

tsvector

tsvector - sənədin axtarış üçün optimize edilmiş təsviri:

SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector;
-- Result: 'a' 'and' 'ate' 'cat' 'fat' 'mat' 'on' 'rat' 'sat'

tsquery

tsquery - axtarış sorğusu:

SELECT 'fat & rat'::tsquery;
-- Result: 'fat' & 'rat'

to_tsvector və to_tsquery

-- Mətni tsvector-a çevir
SELECT to_tsvector('english', 'The quick brown fox jumps over the lazy dog');
-- Result: 'brown':3 'dog':9 'fox':4 'jump':5 'lazi':8 'quick':2

-- Query yarat
SELECT to_tsquery('english', 'quick & fox');
-- Result: 'quick' & 'fox'

PostgreSQL FTS vs Elasticsearch

XüsusiyyətPostgreSQL FTSElasticsearch
SetupDaxili, əlavə setup lazım deyilAyrıca cluster quraşdırılmalı
PerformansYaxşı (milyon sətirlərə qədər)Excellent (milyardlarla sənəd)
MürəkkəblikSadəKompleks
Dil Dəstəyi20+ dil30+ dil
Fuzzy Searchpg_trgm iləBuilt-in
Distributed SearchMəhdudExcellent
Real-timeVarVar
Memory UsageAşağıYüksək
Sənəd ScoringBasicAdvanced
AggregationSQL iləPowerful DSL

Full-Text Search İstifadə Sahələri

  • Blog və CMS Sistemləri: Məqalə və content axtarışı
  • E-commerce: Məhsul axtarışı
  • Documentation: Sənəd və FAQ axtarışı
  • Forum və Social Media: Post və comment axtarışı
  • Knowledge Base: Bilgi bazası axtarışı
  • Email Systems: Email axtarışı
  • News Portals: Xəbər axtarışı

Əsas Əməliyyatlar

Sadə Axtarış

-- Cədvəl yarat
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title TEXT,
body TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Məlumat əlavə et
INSERT INTO articles (title, body) VALUES
('PostgreSQL Tutorial', 'Learn PostgreSQL database fundamentals'),
('Full-Text Search Guide', 'Complete guide to PostgreSQL FTS'),
('Advanced SQL Queries', 'Master complex SQL queries');

-- Sadə axtarış
SELECT * FROM articles
WHERE to_tsvector('english', title || ' ' || body)
@@ to_tsquery('english', 'PostgreSQL');

tsvector Sütunu Əlavə Etmək

-- tsvector sütunu əlavə et
ALTER TABLE articles ADD COLUMN tsv tsvector;

-- tsvector-u yenilə
UPDATE articles
SET tsv = to_tsvector('english', coalesce(title, '') || ' ' || coalesce(body, ''));

-- İndeks yarat
CREATE INDEX idx_articles_tsv ON articles USING GIN(tsv);

-- Axtarış et
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL & tutorial');

Trigger ilə Avtomatik Yeniləmə

-- Trigger function yarat
CREATE FUNCTION articles_tsv_trigger() RETURNS trigger AS $$
BEGIN
NEW.tsv := to_tsvector('english', coalesce(NEW.title, '') || ' ' || coalesce(NEW.body, ''));
RETURN NEW;
END
$$ LANGUAGE plpgsql;

-- Trigger əlavə et
CREATE TRIGGER tsvectorupdate
BEFORE INSERT OR UPDATE ON articles
FOR EACH ROW
EXECUTE FUNCTION articles_tsv_trigger();

-- Test et
INSERT INTO articles (title, body)
VALUES ('New Article', 'This is a new article about databases');

Weighted Search (Çəkili Axtarış)

-- Müxtəlif field-lərə müxtəlif çəkilər ver
ALTER TABLE articles ADD COLUMN tsv_weighted tsvector;

UPDATE articles
SET tsv_weighted =
setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
setweight(to_tsvector('english', coalesce(body, '')), 'B');

CREATE INDEX idx_articles_weighted ON articles USING GIN(tsv_weighted);

-- Axtarış et (title-də tapılanlar daha yüksək rank alacaq)
SELECT title,
ts_rank(tsv_weighted, query) AS rank
FROM articles, to_tsquery('english', 'PostgreSQL') query
WHERE tsv_weighted @@ query
ORDER BY rank DESC;

Query Operatorları

AND, OR, NOT Operatorları

-- AND (&)
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL & tutorial');

-- OR (|)
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL | MySQL');

-- NOT (!)
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL & !MySQL');

-- Combination
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', '(PostgreSQL | MySQL) & tutorial');
-- Phrase axtarışı (<->)
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'full <-> text <-> search');

-- Distance ilə phrase axtarışı
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL <2> tutorial');
-- Prefix axtarışı (:*)
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'data:*');
-- 'data', 'database', 'databases' tapacaq

Ranking və Sıralama

ts_rank

-- Sadə ranking
SELECT title,
ts_rank(tsv, query) AS rank
FROM articles, to_tsquery('english', 'PostgreSQL') query
WHERE tsv @@ query
ORDER BY rank DESC;

ts_rank_cd (Cover Density)

-- Cover density ranking
SELECT title,
ts_rank_cd(tsv, query) AS rank
FROM articles, to_tsquery('english', 'PostgreSQL & database') query
WHERE tsv @@ query
ORDER BY rank DESC;

Weighted Ranking

-- Weighted ranking (weights: D=0.1, C=0.2, B=0.4, A=1.0)
SELECT title,
ts_rank(tsv_weighted, query, 1) AS rank
FROM articles, to_tsquery('english', 'PostgreSQL') query
WHERE tsv_weighted @@ query
ORDER BY rank DESC;

Highlighting (Vurğulama)

ts_headline

-- Axtarış nəticələrini vurğula
SELECT ts_headline('english', body,
to_tsquery('english', 'PostgreSQL'),
'StartSel=<b>, StopSel=</b>') AS highlighted
FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL');

Özelleşdirilmiş Highlighting

-- Daha çox kontekst göstər
SELECT ts_headline('english', body,
to_tsquery('english', 'PostgreSQL'),
'MaxWords=35, MinWords=15, ShortWord=3,
StartSel=<mark>, StopSel=</mark>') AS highlighted
FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL');

Fuzzy Search (pg_trgm)

Trigram Extension

-- Extension-u aktivləşdir
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- Trigram indeks yarat
CREATE INDEX idx_articles_title_trgm ON articles USING GIN(title gin_trgm_ops);

-- Similarity axtarışı
SELECT title, similarity(title, 'PostgreSQL') AS sim
FROM articles
WHERE title % 'PostgreSQL' -- % operatoru similarity threshold-u yoxlayır
ORDER BY sim DESC;

-- Fuzzy search
SELECT * FROM articles
WHERE title ILIKE '%postgre%' -- Typo-ları da tapa bilir
OR similarity(title, 'postgre') > 0.3;

Multi-Language Support

Dil Konfiqurasiyaları

-- Mövcud konfiqurasiyalara bax
SELECT cfgname FROM pg_ts_config;
-- english, simple, turkish, russian və s.

-- Müxtəlif dillərdə axtarış
SELECT to_tsvector('turkish', 'Bu bir Türkçe mətndir');
SELECT to_tsvector('russian', 'Это русский текст');

Custom Configuration

-- Custom konfiqurasiya yarat
CREATE TEXT SEARCH CONFIGURATION my_config (COPY = english);

-- Stop words əlavə et
CREATE TEXT SEARCH DICTIONARY my_stopwords (
TEMPLATE = pg_catalog.simple,
STOPWORDS = english
);

Performance Optimization

İndeks Növləri

-- GIN indeks (ümumi istifadə)
CREATE INDEX idx_gin ON articles USING GIN(tsv);

-- GiST indeks (daha az yer tutur, ancaq yavaşdır)
CREATE INDEX idx_gist ON articles USING GIST(tsv);

Partial İndeks

-- Yalnız aktiv məqalələr üçün
CREATE INDEX idx_active_articles_tsv
ON articles USING GIN(tsv)
WHERE active = true;

Statistika

-- Statistika yenilə
ANALYZE articles;

-- İndeks istifadəsinə bax
EXPLAIN ANALYZE
SELECT * FROM articles
WHERE tsv @@ to_tsquery('english', 'PostgreSQL');

Best Practices

  1. İndeksləmə: GIN indeks istifadə edin (GiST-dən sürətli)
  2. Trigger: Avtomatik tsvector yeniləməsi üçün trigger istifadə edin
  3. Weighted Search: Müxtəlif field-lərə müxtəlif çəkilər verin
  4. Language: Düzgün dil konfiqurasiyası seçin
  5. Normalization: Mətnləri lowercase-ə çevirin
  6. Caching: Tez-tez istifadə olunan query-ləri cache-ləyin
  7. Limit Results: LIMIT istifadə edərək nəticələri məhdudlaşdırın
  8. Monitoring: Query performansını izləyin

FTS vs LIKE/ILIKE

-- LIKE (yavaş, indeks istifadə etmir)
SELECT * FROM articles WHERE body LIKE '%PostgreSQL%';

-- FTS (sürətli, indeks istifadə edir)
SELECT * FROM articles WHERE tsv @@ to_tsquery('english', 'PostgreSQL');

Real-World Nümunə

-- E-commerce məhsul axtarışı
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT,
description TEXT,
category TEXT,
price DECIMAL(10,2),
tsv tsvector
);

-- Weighted tsvector (name-ə daha çox çəki)
CREATE OR REPLACE FUNCTION products_tsv_trigger() RETURNS trigger AS $$
BEGIN
NEW.tsv :=
setweight(to_tsvector('english', coalesce(NEW.name, '')), 'A') ||
setweight(to_tsvector('english', coalesce(NEW.description, '')), 'B') ||
setweight(to_tsvector('english', coalesce(NEW.category, '')), 'C');
RETURN NEW;
END
$$ LANGUAGE plpgsql;

CREATE TRIGGER tsvectorupdate
BEFORE INSERT OR UPDATE ON products
FOR EACH ROW
EXECUTE FUNCTION products_tsv_trigger();

CREATE INDEX idx_products_tsv ON products USING GIN(tsv);

-- Axtarış query
SELECT name, price,
ts_rank(tsv, query) AS rank,
ts_headline('english', description, query,
'MaxWords=20, StartSel=<b>, StopSel=</b>') AS snippet
FROM products, to_tsquery('english', 'laptop & gaming') query
WHERE tsv @@ query
ORDER BY rank DESC
LIMIT 10;

Əlavə Resurslar