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`.

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)
	}
}