How to Implement Full-Text Search with PostgreSQL in Go
PostgreSQL full-text search in Go requires enabling the tsvector and tsquery types in your schema, then querying them using the @@ operator via a standard SQL driver like lib/pq.
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
type Document struct {
ID int
Title string
}
func main() {
// Connect to database
db, err := sql.Open("postgres", "user=postgres dbname=example sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 1. Create table with GIN index for performance
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS documents (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
search_vector TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', title || ' ' || content)) STORED
);
CREATE INDEX IF NOT EXISTS idx_search_vector ON documents USING GIN(search_vector);
`)
if err != nil {
log.Fatal(err)
}
// 2. Query using the @@ operator with plainto_tsquery
var results []Document
query := `SELECT id, title FROM documents WHERE search_vector @@ plainto_tsquery('english', $1)`
rows, err := db.Query(query, "database & search")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var doc Document
if err := rows.Scan(&doc.ID, &doc.Title); err != nil {
log.Fatal(err)
}
results = append(results, doc)
}
if err = rows.Err(); err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d documents\n", len(results))
for _, doc := range results {
fmt.Printf("ID: %d, Title: %s\n", doc.ID, doc.Title)
}
}