Ana içeriğe geç
Kesit SQL
İleri · SQL Türlerine Özgü

Tam metin arama: LIKE yerine dizinli kelime araması

PostgreSQL tsvector, SQL Server CONTAINS, MySQL MATCH AGAINST, SQLite FTS; sıralama ve Türkçe.

Uygulamada aç, 8 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

LIKE'ın sınırları

WHERE aciklama LIKE '%kablosuz%' her satırı baştan sona tarar (baştaki % yüzünden indeks kullanılamaz), kelime köklerini bilmez (“kulaklıklar”ı bulmaz) ve sonuçları alaka düzeyine göre sıralayamaz. Tam metin arama metni kelimelere (token) ayırıp ters dizin (inverted index) oluşturur.

SQLite FTS ile deneyelim

CREATE VIRTUAL TABLE urun_ara USING fts4(name, category);
INSERT INTO urun_ara (docid, name, category) SELECT product_id, name, category FROM products;

SELECT docid AS product_id, name
FROM urun_ara
WHERE urun_ara MATCH 'kablosuz OR bluetooth';

SQL türlerine göre

-- PostgreSQL
ALTER TABLE products ADD COLUMN arama tsvector
  GENERATED ALWAYS AS (to_tsvector('turkish', coalesce(name, '') || ' ' || coalesce(category, ''))) STORED;
CREATE INDEX ix_products_arama ON products USING GIN (arama);

SELECT name, ts_rank(arama, q) AS puan
FROM products, websearch_to_tsquery('turkish', 'kablosuz kulaklık') AS q
WHERE arama @@ q
ORDER BY puan DESC;

-- Benzer yazım için: CREATE EXTENSION pg_trgm; WHERE name % 'kulaklik'

-- SQL Server
CREATE FULLTEXT CATALOG ftc AS DEFAULT;
CREATE FULLTEXT INDEX ON dbo.products (name LANGUAGE 1055) KEY INDEX PK_products;  -- 1055 = Türkçe
SELECT name FROM dbo.products WHERE CONTAINS(name, N'"kablosuz*"');
SELECT name FROM dbo.products WHERE FREETEXT(name, N'kablosuz kulaklık');

-- MySQL (InnoDB)
ALTER TABLE products ADD FULLTEXT INDEX ft_name (name);
SELECT name, MATCH(name) AGAINST('kablosuz kulaklık' IN NATURAL LANGUAGE MODE) AS puan
FROM products WHERE MATCH(name) AGAINST('+kablosuz -hoparlör' IN BOOLEAN MODE);

-- Oracle Text
CREATE INDEX ix_ad ON products (name) INDEXTYPE IS CTXSYS.CONTEXT;
SELECT name, SCORE(1) FROM products WHERE CONTAINS(name, 'kablosuz', 1) > 0 ORDER BY SCORE(1) DESC;

-- BigQuery
CREATE SEARCH INDEX ix_ara ON anadolu.products (name);
SELECT name FROM anadolu.products WHERE SEARCH(name, 'kablosuz');

Türkçe dikkat noktaları

Alıştırmalara geç (8)