Semua bahan sudah tersedia: tsvector menyimpan dokumen sebagai lexeme, tsquery menyimpan kueri beroperator, dan fungsi konversi menghubungkan keduanya dengan teks mentah. Pada chapter ini kita merangkai seluruhnya menjadi alur kerja pencarian yang utuh pada tabel artikel — mulai dari query WHERE yang menggabungkan judul dan isi menjadi satu dokumen, variasi kueri untuk frasa dan pengecualian, pengurutan hasil berdasarkan skor relevansi ts_rank, sampai cuplikan hasil bertanda dari ts_headline. Chapter ini juga memperkenalkan dua pola yang dipakai hampir semua aplikasi nyata: memberi bobot berbeda pada bagian dokumen, dan menyimpan tsvector sebagai kolom yang terisi otomatis.
Pencarian pada Dokumen Gabungan #
Fitur pencarian sebuah blog jarang hanya menelusuri satu kolom; pengguna mengetik belajar php dan berharap judul maupun isi artikel ikut diperiksa. Pola standarnya: gabungkan kolom-kolom teks dengan operator || menjadi satu dokumen, lalu proses dengan to_tsvector. Sesuai pembahasan chapter sebelumnya, korpus kita yang berbahasa Indonesia campur Inggris memakai konfigurasi simple:
-- Tabel artikel: korpus kecil untuk demo full-text search.
CREATE TABLE artikel (
id integer PRIMARY KEY,
judul text NOT NULL,
isi text NOT NULL
);
INSERT INTO artikel (id, judul, isi) VALUES
(1, 'Belajar PHP untuk Pemula',
'PHP adalah bahasa pemrograman server side yang populer. Di kelas pemula ini kita belajar variabel, function, dan array. Setiap materi disertai contoh kode yang bisa dijalankan langsung.'),
(2, 'Migrasi Database dari MySQL ke PostgreSQL',
'Migrasi skema dari MySQL ke PostgreSQL butuh persiapan. Pelajari perbedaan tipe data, konfigurasi transaction, dan fitur window function terlebih dahulu. Uji coba di server staging lebih dulu.'),
(3, 'Tips Menulis Query SQL yang Cepat',
'Query yang lambat biasanya bermula dari index yang kurang tepat. Belajar membaca execution plan, hindari SELECT *, dan ukur setiap perubahan. Profiling adalah kunci tuning database.'),
(4, 'Mengajar Data Science untuk Anak SMA',
'Program mengajar data science di sekolah menekankan praktik. Siswa mengolah data penjualan dengan spreadsheet lalu naik kelas ke SQL. Para guru mempelajari statistik dasar lebih dulu, lalu mengajarkan visualisasi data.'),
(5, 'Memilih Database untuk Aplikasi Startup',
'Setiap database punya kekuatan sendiri. PostgreSQL unggul di fitur JSONB dan full text search, sementara MySQL familiar di hosting murah. Sesuaikan pilihan dengan kebutuhan tim, bukan tren.'),
(6, 'Belajar DevOps: Docker dan CI/CD',
'Modul belajar DevOps membahas container Docker, pipeline CI/CD, dan monitoring. Pipeline berjalan otomatis setiap push, dengan jobs running in parallel untuk mempercepat feedback. Semua lab berjalan di virtual machine.'),
(7, 'Wawancara dengan Alumni Bootcamp',
'Beliau kini bekerja sebagai backend engineer di sebuah startup logistik. Cerita alumni bootcamp ini menyoroti disiplin latihan, portofolio yang rapi, dan kebiasaan menulis dokumentasi. Rekruter menilai konsistensi lebih dari sertifikat.'),
(8, 'Panduan Full Text Search di PostgreSQL',
'Full text search mencocokkan akar kata, bukan pola karakter. Katalog toko online yang menulis sepatu untuk berlari tetap ditemukan pencari sepatu lari. Kita akan belajar tsvector dan tsquery langkah demi langkah.');Output yang Dihasilkan:
CREATE TABLE
INSERT 0 8Empat variasi kueri berikut menunjukkan rentang kendali yang tersedia langsung di klausa WHERE:
-- Hasil to_tsvector pada judul: lexeme plus posisi kata aslinya.
SELECT to_tsvector('simple', judul) AS dokumen_judul
FROM artikel
WHERE id = 1;
-- Pencarian satu kata pada dokumen gabungan judul dan isi.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar')
ORDER BY id;
-- Dua kata yang harus hadir bersamaan.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & php')
ORDER BY id;
-- Kata yang justru dilarang hadir.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & !php')
ORDER BY id;
-- Ganti konfigurasi ke 'indonesian': bentuk kata berkerabat ikut tertangkap.
SELECT id, judul FROM artikel
WHERE to_tsvector('indonesian', judul || ' ' || isi) @@ to_tsquery('indonesian', 'belajar')
ORDER BY id;Output yang Dihasilkan:
dokumen_judul
------------------------------------------
'belajar':1 'pemula':4 'php':2 'untuk':3
(1 row)
id | judul
----+----------------------------------------
1 | Belajar PHP untuk Pemula
3 | Tips Menulis Query SQL yang Cepat
6 | Belajar DevOps: Docker dan CI/CD
8 | Panduan Full Text Search di PostgreSQL
(4 rows)
id | judul
----+--------------------------
1 | Belajar PHP untuk Pemula
(1 row)
id | judul
----+----------------------------------------
3 | Tips Menulis Query SQL yang Cepat
6 | Belajar DevOps: Docker dan CI/CD
8 | Panduan Full Text Search di PostgreSQL
(3 rows)
id | judul
----+-------------------------------------------
1 | Belajar PHP untuk Pemula
2 | Migrasi Database dari MySQL ke PostgreSQL
3 | Tips Menulis Query SQL yang Cepat
4 | Mengajar Data Science untuk Anak SMA
6 | Belajar DevOps: Docker dan CI/CD
8 | Panduan Full Text Search di PostgreSQL
(6 rows)Mari kita bedah hasilnya satu per satu:
dokumen_judul: judul artikel id 1 menjadi'belajar':1 'pemula':4 'php':2 'untuk':3— kata terurut sebagai lexeme, posisi mengacu pada urutan kata asli di judul.- Kata tunggal
belajar: empat artikel cocok (id 1, 3, 6, 8) — tepat artikel yang memuat katabelajarsecara harfiah, karena konfigurasisimpletidak melakukan stemming. belajar & php: tinggal artikel id 1 — satu-satunya yang memuat kedua kata sekaligus.belajar & !php: artikel 3, 6, dan 8 — memuatbelajartetapi tidak memuatphp.- Konfigurasi
indonesian: jumlah hasil melonjak menjadi enam (id 1, 2, 3, 4, 6, 8) karenaPelajari,mengajar, danmempelajariruntuh ke akarajaryang sama denganbelajar. Pilihan konfigurasi benar-benar mengubah hasil; tidak ada yang salah dari keduanya —simplememberi presisi kata,indonesianmemberi jangkauan bentuk kata.
Frasa dan Gaya Kotak Pencarian #
Operator frasa membedakan “kata-kata ini berurutan” dari “kata-kata ini ada di mana saja”. Perbedaannya terlihat paling jelas saat membandingkan kueri AND biasa dengan phraseto_tsquery pada kata yang sama:
-- Frasa: kata harus berdampingan dengan urutan yang persis sama.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ phraseto_tsquery('simple', 'belajar database')
ORDER BY id;
-- Kata-kata yang sama tanpa syarat urutan.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & database')
ORDER BY id;
-- Gaya kotak pencarian: frasa dalam tanda kutip.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ websearch_to_tsquery('simple', '"belajar php"')
ORDER BY id;
-- Gaya kotak pencarian: pengecualian dengan tanda minus.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ websearch_to_tsquery('simple', 'belajar -php')
ORDER BY id;
-- Gaya kotak pencarian: alternatif dengan OR.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ websearch_to_tsquery('simple', 'docker OR jsonb')
ORDER BY id;Output yang Dihasilkan:
id | judul
----+-------
(0 rows)
id | judul
----+-----------------------------------
3 | Tips Menulis Query SQL yang Cepat
(1 row)
id | judul
----+--------------------------
1 | Belajar PHP untuk Pemula
(1 row)
id | judul
----+----------------------------------------
3 | Tips Menulis Query SQL yang Cepat
6 | Belajar DevOps: Docker dan CI/CD
8 | Panduan Full Text Search di PostgreSQL
(3 rows)
id | judul
----+-----------------------------------------
5 | Memilih Database untuk Aplikasi Startup
6 | Belajar DevOps: Docker dan CI/CD
(2 rows)Dua baris pertama adalah inti pelajaran frasa. Artikel id 3 memuat belajar di satu kalimat dan database di kalimat penutup, sehingga kueri belajar & database menemukannya — tetapi phraseto_tsquery('simple', 'belajar database') menghasilkan nol baris karena kedua kata tidak pernah berdampingan dalam urutan itu. Tiga kueri sisanya memperlihatkan websearch_to_tsquery yang paling cocok dipasang tepat di belakang kotak pencarian aplikasi: "belajar php" hanya menjaring artikel id 1 yang judulnya persis diawali frasa tersebut, belajar -php menyaring artikel ber-php, dan docker OR jsonb menjaring dua artikel yang menyebut salah satu istilah.
Mengurutkan Hasil dengan Skor Relevansi #
Daftar hasil pencarian yang tidak terurut terasa datar; mesin pencari selalu menampilkan dokumen paling relevan lebih dulu. Fungsi ts_rank(dokumen, kueri) menghitung skor dari frekuensi kecocokan, dan ts_rank_cd menghitung cover density — seberapa rapat kata kunci berkumpul dalam dokumen:
-- Skor relevansi: artikel yang menyebut kata kunci lebih sering mendapat skor lebih tinggi.
SELECT id, judul,
ts_rank(to_tsvector('simple', judul || ' ' || isi), to_tsquery('simple', 'belajar')) AS skor
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar')
ORDER BY skor DESC, id;
-- ts_rank_cd mengukur kepadatan kata kunci di dokumen, bukan hanya frekuensinya.
SELECT id,
ts_rank(to_tsvector('simple', judul || ' ' || isi), to_tsquery('simple', 'belajar')) AS skor_biasa,
ts_rank_cd(to_tsvector('simple', judul || ' ' || isi), to_tsquery('simple', 'belajar')) AS skor_cd
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar')
ORDER BY skor_biasa DESC, skor_cd DESC, id;Output yang Dihasilkan:
id | judul | skor
----+----------------------------------------+-------------
1 | Belajar PHP untuk Pemula | 0.075990885
6 | Belajar DevOps: Docker dan CI/CD | 0.075990885
3 | Tips Menulis Query SQL yang Cepat | 0.06079271
8 | Panduan Full Text Search di PostgreSQL | 0.06079271
(4 rows)
id | skor_biasa | skor_cd
----+-------------+---------
1 | 0.075990885 | 0.2
6 | 0.075990885 | 0.2
3 | 0.06079271 | 0.1
8 | 0.06079271 | 0.1
(4 rows)Angka-angka hasilnya mudah dibaca: artikel 1 dan 6 menyebut belajar dua kali (judul dan isi) sehingga skor ts_rank-nya 0.075990885, sedangkan artikel 3 dan 8 yang hanya menyebut sekali mendapat 0.06079271. Versi ts_rank_cd menghasilkan angka berbeda (0.2 lawan 0.1) karena mengukur kepadatan, bukan frekuensi — untuk kueri multi-kata, fungsi ini membedakan dokumen yang kata kuncinya rapat di satu paragraf dari dokumen yang kata kuncinya tercecer.
Menyorot Hasil dengan ts_headline #
Halaman hasil pencarian menampilkan cuplikan, bukan dokumen penuh. Fungsi ts_headline(konfigurasi, dokumen, kueri) mengembalikan potongan teks asli dengan penanda HTML di sekitar kata yang dicocokkan:
-- Cuplikan isi dengan penanda di sekitar kata yang dicari.
SELECT id, ts_headline('simple', isi, to_tsquery('simple', 'belajar & php')) AS cuplikan
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & php')
ORDER BY id;
-- ts_headline juga bekerja pada judul dan kueri satu kata.
SELECT id, ts_headline('simple', judul, to_tsquery('simple', 'docker')) AS cuplikan_judul
FROM artikel
WHERE id = 6;Output yang Dihasilkan:
id | cuplikan
----+-----------------------------------------------------------------------------------------------------------------
1 | <b>PHP</b> adalah bahasa pemrograman server side yang populer. Di kelas pemula ini kita <b>belajar</b> variabel
(1 row)
id | cuplikan_judul
----+-----------------------------------------
6 | Belajar DevOps: <b>Docker</b> dan CI/CD
(1 row)Cuplikan artikel id 1 memperlihatkan perilakunya: kata PHP dan belajar dibungkus tag <b> dan </b>, dan teks dipadatkan di sekitar kata yang dicocokkan — cuplikan pertama berhenti setelah kata variabel karena kata kunci terakhir sudah tercakup. Tag penanda bisa diganti lewat opsi seperti StartSel dan StopSel; cuplikan judul artikel id 6 menunjukkan bahwa fungsi ini tidak terbatas pada kolom isi.
Bobot Bagian Dokumen dan Kolom Tersimpan #
Skor sejauh ini memperlakukan judul dan isi sama rata, padahal kecocokan di judul biasanya lebih bermakna daripada kecocokan di isi. Fungsi setweight memberi label bobot pada setiap posisi tsvector, lalu skor ts_rank mengalikan kecocokan dengan bobotnya. Konvensi umum menempatkan judul di bobot A (paling berat) dan isi di D (paling ringan); posisi tanpa label otomatis dianggap D:
-- Beri label bobot: judul diberi bobot A (paling berat), isi diberi bobot D.
SELECT id, judul,
ts_rank(
setweight(to_tsvector('simple', judul), 'A') || setweight(to_tsvector('simple', isi), 'D'),
to_tsquery('simple', 'devops | jsonb')
) AS skor_bobot
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'devops | jsonb')
ORDER BY skor_bobot DESC, id;
-- Simpan dokumen sebagai kolom generated agar tidak dihitung ulang di setiap query.
ALTER TABLE artikel ADD COLUMN dokumen tsvector
GENERATED ALWAYS AS (to_tsvector('simple', judul || ' ' || isi)) STORED;
SELECT id, judul FROM artikel
WHERE dokumen @@ to_tsquery('simple', 'belajar & !php')
ORDER BY id;
SELECT id, judul FROM artikel
WHERE dokumen @@ websearch_to_tsquery('simple', '"belajar php"')
ORDER BY id;Output yang Dihasilkan:
id | judul | skor_bobot
----+-----------------------------------------+-------------
6 | Belajar DevOps: Docker dan CI/CD | 0.31156266
5 | Memilih Database untuk Aplikasi Startup | 0.030396355
(2 rows)
ALTER TABLE
id | judul
----+----------------------------------------
3 | Tips Menulis Query SQL yang Cepat
6 | Belajar DevOps: Docker dan CI/CD
8 | Panduan Full Text Search di PostgreSQL
(3 rows)
id | judul
----+--------------------------
1 | Belajar PHP untuk Pemula
(1 row)Perhatikan lompatan skor: kueri devops | jsonb memberi artikel id 6 skor 0.31156266 karena DevOps ditemukan di judul berbobot A, sementara JSONB di isi artikel id 5 “hanya” bernilai 0.030396355. Rasio keduanya mencerminkan tangga bobot yang Anda tetapkan sendiri. Pola setweight(...) || setweight(...) ini sekaligus penerapan operator || yang kita temui di chapter tsvector dan tsquery — posisi kedua vector dirantai ulang otomatis.
Bagian kedua file memperkenalkan pola penyimpanan. Kolom dokumen dideklarasikan sebagai generated column STORED, sehingga PostgreSQL menghitung to_tsvector pada saat baris di-INSERT atau di-UPDATE dan menyimpan hasilnya di disk — dua query terakhir memakai kolom itu langsung tanpa menyebut to_tsvector lagi. Ekspresinya harus deterministik; itulah sebabnya konfigurasi ditulis eksplisit sebagai argumen pertama to_tsvector('simple', ...), bukan dititipkan pada konfigurasi default sesi. Pembahasan penuh generated columns ada di chapter Generated Columns
.
Alur kerja pencarian kita kini lengkap: dokumen gabungan, variasi kueri, skor relevansi, cuplikan berpenanda, bobot per bagian dokumen, dan penyimpanan tsvector yang terawat otomatis. Dua topik masih menunggu di depan: mengupas ts_rank dan ts_rank_cd lebih dalam — normalisasi skor, penalaan bobot — di chapter Ranking Hasil Pencarian, serta mengendalikan konfigurasi bahasa untuk teks Indonesia di chapter Konfigurasi Bahasa.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
bobot-dan-kolom.sql
Unduh berkas-- Beri label bobot: judul diberi bobot A (paling berat), isi diberi bobot D.
SELECT id, judul,
ts_rank(
setweight(to_tsvector('simple', judul), 'A') || setweight(to_tsvector('simple', isi), 'D'),
to_tsquery('simple', 'devops | jsonb')
) AS skor_bobot
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'devops | jsonb')
ORDER BY skor_bobot DESC, id;
-- Simpan dokumen sebagai kolom generated agar tidak dihitung ulang di setiap query.
ALTER TABLE artikel ADD COLUMN dokumen tsvector
GENERATED ALWAYS AS (to_tsvector('simple', judul || ' ' || isi)) STORED;
SELECT id, judul FROM artikel
WHERE dokumen @@ to_tsquery('simple', 'belajar & !php')
ORDER BY id;
SELECT id, judul FROM artikel
WHERE dokumen @@ websearch_to_tsquery('simple', '"belajar php"')
ORDER BY id;
buat-tabel.sql
Unduh berkas-- Tabel artikel: korpus kecil untuk demo full-text search.
CREATE TABLE artikel (
id integer PRIMARY KEY,
judul text NOT NULL,
isi text NOT NULL
);
INSERT INTO artikel (id, judul, isi) VALUES
(1, 'Belajar PHP untuk Pemula',
'PHP adalah bahasa pemrograman server side yang populer. Di kelas pemula ini kita belajar variabel, function, dan array. Setiap materi disertai contoh kode yang bisa dijalankan langsung.'),
(2, 'Migrasi Database dari MySQL ke PostgreSQL',
'Migrasi skema dari MySQL ke PostgreSQL butuh persiapan. Pelajari perbedaan tipe data, konfigurasi transaction, dan fitur window function terlebih dahulu. Uji coba di server staging lebih dulu.'),
(3, 'Tips Menulis Query SQL yang Cepat',
'Query yang lambat biasanya bermula dari index yang kurang tepat. Belajar membaca execution plan, hindari SELECT *, dan ukur setiap perubahan. Profiling adalah kunci tuning database.'),
(4, 'Mengajar Data Science untuk Anak SMA',
'Program mengajar data science di sekolah menekankan praktik. Siswa mengolah data penjualan dengan spreadsheet lalu naik kelas ke SQL. Para guru mempelajari statistik dasar lebih dulu, lalu mengajarkan visualisasi data.'),
(5, 'Memilih Database untuk Aplikasi Startup',
'Setiap database punya kekuatan sendiri. PostgreSQL unggul di fitur JSONB dan full text search, sementara MySQL familiar di hosting murah. Sesuaikan pilihan dengan kebutuhan tim, bukan tren.'),
(6, 'Belajar DevOps: Docker dan CI/CD',
'Modul belajar DevOps membahas container Docker, pipeline CI/CD, dan monitoring. Pipeline berjalan otomatis setiap push, dengan jobs running in parallel untuk mempercepat feedback. Semua lab berjalan di virtual machine.'),
(7, 'Wawancara dengan Alumni Bootcamp',
'Beliau kini bekerja sebagai backend engineer di sebuah startup logistik. Cerita alumni bootcamp ini menyoroti disiplin latihan, portofolio yang rapi, dan kebiasaan menulis dokumentasi. Rekruter menilai konsistensi lebih dari sertifikat.'),
(8, 'Panduan Full Text Search di PostgreSQL',
'Full text search mencocokkan akar kata, bukan pola karakter. Katalog toko online yang menulis sepatu untuk berlari tetap ditemukan pencari sepatu lari. Kita akan belajar tsvector dan tsquery langkah demi langkah.');
headline.sql
Unduh berkas-- Cuplikan isi dengan penanda di sekitar kata yang dicari.
SELECT id, ts_headline('simple', isi, to_tsquery('simple', 'belajar & php')) AS cuplikan
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & php')
ORDER BY id;
-- ts_headline juga bekerja pada judul dan kueri satu kata.
SELECT id, ts_headline('simple', judul, to_tsquery('simple', 'docker')) AS cuplikan_judul
FROM artikel
WHERE id = 6;
pencarian-dasar.sql
Unduh berkas-- Hasil to_tsvector pada judul: lexeme plus posisi kata aslinya.
SELECT to_tsvector('simple', judul) AS dokumen_judul
FROM artikel
WHERE id = 1;
-- Pencarian satu kata pada dokumen gabungan judul dan isi.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar')
ORDER BY id;
-- Dua kata yang harus hadir bersamaan.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & php')
ORDER BY id;
-- Kata yang justru dilarang hadir.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & !php')
ORDER BY id;
-- Ganti konfigurasi ke 'indonesian': bentuk kata berkerabat ikut tertangkap.
SELECT id, judul FROM artikel
WHERE to_tsvector('indonesian', judul || ' ' || isi) @@ to_tsquery('indonesian', 'belajar')
ORDER BY id;
pencarian-frasa.sql
Unduh berkas-- Frasa: kata harus berdampingan dengan urutan yang persis sama.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ phraseto_tsquery('simple', 'belajar database')
ORDER BY id;
-- Kata-kata yang sama tanpa syarat urutan.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar & database')
ORDER BY id;
-- Gaya kotak pencarian: frasa dalam tanda kutip.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ websearch_to_tsquery('simple', '"belajar php"')
ORDER BY id;
-- Gaya kotak pencarian: pengecualian dengan tanda minus.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ websearch_to_tsquery('simple', 'belajar -php')
ORDER BY id;
-- Gaya kotak pencarian: alternatif dengan OR.
SELECT id, judul FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ websearch_to_tsquery('simple', 'docker OR jsonb')
ORDER BY id;
ranking.sql
Unduh berkas-- Skor relevansi: artikel yang menyebut kata kunci lebih sering mendapat skor lebih tinggi.
SELECT id, judul,
ts_rank(to_tsvector('simple', judul || ' ' || isi), to_tsquery('simple', 'belajar')) AS skor
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar')
ORDER BY skor DESC, id;
-- ts_rank_cd mengukur kepadatan kata kunci di dokumen, bukan hanya frekuensinya.
SELECT id,
ts_rank(to_tsvector('simple', judul || ' ' || isi), to_tsquery('simple', 'belajar')) AS skor_biasa,
ts_rank_cd(to_tsvector('simple', judul || ' ' || isi), to_tsquery('simple', 'belajar')) AS skor_cd
FROM artikel
WHERE to_tsvector('simple', judul || ' ' || isi) @@ to_tsquery('simple', 'belajar')
ORDER BY skor_biasa DESC, skor_cd DESC, id;