searchsql

package
v0.12.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

@index Shared search backend interface and errors for SQLite FTS5 and PostgreSQL tsvector implementations.

@index PostgreSQL tsvector + GIN based full-text search backend implementation (including schema, triggers, and queries).

@index Bound SQL search and retrieval persistence adapters.

@index Query sanitizers for backend-specific full-text search syntax.

@index SQLite FTS5 virtual table-based full-text search backend implementation (including migration, legacy upgrades, and incremental re-indexing).

@index Search-document refresh and FTS content generation.

Index

Constants

This section is empty.

Variables

View Source
var ErrFTS5NotAvailable = trace.New("fts5 module not available")

ErrFTS5NotAvailable indicates the SQLite build lacks the fts5 extension.

Functions

func NewIngestUnitOfWork

func NewIngestUnitOfWork(db *gorm.DB, backend Backend, logger *slog.Logger) ingest.UnitOfWork

NewIngestUnitOfWork composes transaction-scoped graph and search adapters for ingest workflows. @intent keep raw GORM transaction wiring at the outbound composition boundary.

func RefreshSearchDocuments

func RefreshSearchDocuments(ctx context.Context, db *gorm.DB) (int, error)

RefreshSearchDocuments rebuilds namespace-scoped search_documents from current graph nodes. @intent keep derived search documents consistent with graph state before FTS rebuilds

func RefreshSearchDocumentsFor

func RefreshSearchDocumentsFor(ctx context.Context, db *gorm.DB, nodeIDs []uint) (int, error)

RefreshSearchDocumentsFor rebuilds search_documents for the specified node IDs only. @intent incremental update 경로에서 영향받은 문서만 갱신한다.

func SanitizeFTS5

func SanitizeFTS5(query string) string

SanitizeFTS5 converts raw user input into a safe FTS5 prefix query. A camelCase term also matches its sub-tokens, so `getUser` matches either the whole token or (`get` AND `user`), mirroring the sub-tokens indexed at build time. @intent build SQLite FTS queries that preserve prefix matching without exposing parser-breaking characters. @domainRule empty or fully stripped input returns an empty query string.

func SanitizePostgresTSQuery

func SanitizePostgresTSQuery(query string) string

SanitizePostgresTSQuery converts raw user input into a safe prefix tsquery, mirroring SanitizeFTS5 including camelCase sub-token expansion. @intent translate free-form user input into a PostgreSQL tsquery that mirrors the SQLite prefix search behavior. @domainRule empty or fully stripped input returns an empty query string.

Types

type Backend

type Backend interface {
	// @intent prepare search tables and indexes for the active database driver.
	// @sideEffect may create or update search index schema objects.
	Migrate(db *gorm.DB) error
	// @intent refresh backend-specific full-text index state from the current persisted search documents for the active namespace.
	// @requires db must be a valid connection for processing the active namespace.
	// @sideEffect rewrites backend-specific search index records or derived vectors.
	Rebuild(ctx context.Context, db *gorm.DB) error
	// @intent reindex only changed nodes so incremental updates cost less than full rebuilds.
	// @param nodeIDs is the set of node IDs to reindex.
	// @sideEffect updates search index records for the specified nodes.
	RebuildNodes(ctx context.Context, db *gorm.DB, nodeIDs []uint) error
	// @intent remove or reconcile backend-specific search index state for the active namespace when physical cleanup is required.
	// @sideEffect may clear namespace-scoped search index records, though implementations may intentionally no-op.
	PurgeNamespace(ctx context.Context, db *gorm.DB) error
	// @intent execute a user query using the backend-specific full-text search syntax.
	// @param query is the raw query string to search for.
	// @param limit is the maximum number of results to return.
	// @return returns nodes ordered by relevance.
	Query(ctx context.Context, db *gorm.DB, query string, limit int) ([]graph.Node, error)
}

Backend defines the full-text search backend contract. @intent provide one interface for backend-specific search index migration, rebuild, and query operations.

type PostgresBackend

type PostgresBackend struct{}

PostgresBackend is a full-text search backend based on PostgreSQL tsvector. @intent Handles full-text search indexing and querying in a PostgreSQL environment.

func NewPostgresBackend

func NewPostgresBackend() *PostgresBackend

NewPostgresBackend creates a PostgreSQL search backend. @intent Provides a Backend implementation specifically for PostgreSQL.

func (*PostgresBackend) Migrate

func (p *PostgresBackend) Migrate(db *gorm.DB) error

Migrate ensures the PostgreSQL search schema exists by running the versioned migrations, which are the single source of truth for the tsvector column, trigger, and GIN index. It no longer hand-writes DDL, so the schema cannot drift from the migration files. @intent give tests and callers a one-call schema setup that reuses the production migrations. @sideEffect applies any pending schema migrations to the connected database.

func (*PostgresBackend) PurgeNamespace

func (p *PostgresBackend) PurgeNamespace(ctx context.Context, db *gorm.DB) error

PurgeNamespace is a no-op as PostgreSQL search_documents deletion does not require separate physical cleanup. @intent Aligns with the Backend interface and maintains consistency in the namespace purge path.

func (*PostgresBackend) Query

func (p *PostgresBackend) Query(ctx context.Context, db *gorm.DB, query string, limit int) ([]graph.Node, error)

Query searches for related nodes using PostgreSQL tsquery.

Every term is required, mirroring the SQLite backend. See SQLiteBackend.Query for why widening to any-term was measured and rejected.

@intent Converts the user's search term into a prefix tsquery to find related nodes. @requires limit must be greater than 0 to get meaningful results. @return Returns a list of nodes sorted by ts_rank.

func (*PostgresBackend) Rebuild

func (p *PostgresBackend) Rebuild(ctx context.Context, db *gorm.DB) error

Rebuild recalculates the tsvector for all search documents. @intent Batch regenerates the full-text search index for existing search_documents rows. @sideEffect Updates search_documents.tsv values.

func (*PostgresBackend) RebuildNodes

func (p *PostgresBackend) RebuildNodes(ctx context.Context, db *gorm.DB, nodeIDs []uint) error

RebuildNodes recalculates the tsvector only for specified nodes. @intent Avoids full namespace tsv updates during incremental update paths.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader binds candidate search and fallback retrieval persistence to one database. @intent adapt raw SQL backend and GORM operations to app/search retrieval ports.

func NewReader

func NewReader(db *gorm.DB, backend Backend) *Reader

NewReader constructs bound search and retrieval ports. @intent keep database handles out of application service construction.

func (*Reader) Annotations

func (r *Reader) Annotations(ctx context.Context, nodeIDs []uint) (map[uint]*graph.Annotation, error)

Annotations batch-loads structured annotations for namespace-owned candidate nodes. @intent provide bounded retrieval evidence without leaking joins into app policy.

func (*Reader) Query

func (r *Reader) Query(ctx context.Context, query string, limit int) ([]graph.Node, error)

Query returns relevance-ordered candidates from the configured SQL search backend. @intent implement the bound candidate-search port without exposing a DB argument.

func (*Reader) ScanCandidates

func (r *Reader) ScanCandidates(ctx context.Context, kinds []graph.NodeKind, limit int) ([]graph.Node, error)

ScanCandidates loads a bounded, deterministic namespace snapshot with annotations. @intent provide sparse-FTS fallback inputs while keeping matching and scoring in app policy.

type SQLiteBackend

type SQLiteBackend struct {
	// contains filtered or unexported fields
}

SQLiteBackend is a full-text search backend based on SQLite FTS5. @intent Handles full-text search indexing and querying in a SQLite environment.

func NewSQLiteBackend

func NewSQLiteBackend() *SQLiteBackend

NewSQLiteBackend creates a SQLite search backend. @intent Provides a Backend implementation specifically for SQLite.

func (*SQLiteBackend) Migrate

func (s *SQLiteBackend) Migrate(db *gorm.DB) error

Migrate prepares the SQLite FTS5 virtual table. @intent Creates a full-text search index table for SQLite. @sideEffect May create the search_fts virtual table. @ensures search_fts exists if FTS5 is available.

func (*SQLiteBackend) PurgeNamespace

func (s *SQLiteBackend) PurgeNamespace(ctx context.Context, db *gorm.DB) error

PurgeNamespace removes the physical FTS index for a specific namespace. @intent Cleans up stale FTS rows even in paths without a rebuild, such as namespace deletion.

func (*SQLiteBackend) Query

func (s *SQLiteBackend) Query(ctx context.Context, db *gorm.DB, query string, limit int) ([]graph.Node, error)

Query searches for related nodes using FTS5 MATCH queries.

Every term is required, and SanitizeFTS5 decides what counts as a term. That pairing is the whole retrieval policy: requiring all terms is right when the searcher typed identifiers, and it only became wrong for sentences because ordinary English words were being required too.

Widening to any-term when all-terms matches nothing was measured and rejected. It answered no query the narrow expression missed — the two extra nodes it retrieved never reached the top ten — and it filled the deliberate nonsense query in the golden set with fifty unrelated hits.

@intent Converts the user's search term into a SQLite FTS prefix query to find nodes. @requires limit must be greater than 0 to get meaningful results. @return Returns a list of nodes sorted by FTS rank.

func (*SQLiteBackend) Rebuild

func (s *SQLiteBackend) Rebuild(ctx context.Context, db *gorm.DB) error

Rebuild reloads search_documents content into the FTS index. @intent Synchronizes stored search documents with the SQLite FTS index. @sideEffect Deletes and re-inserts search_fts content. @domainRule Index content must match the current snapshot of search_documents.

func (*SQLiteBackend) RebuildNodes

func (s *SQLiteBackend) RebuildNodes(ctx context.Context, db *gorm.DB, nodeIDs []uint) error

RebuildNodes synchronizes only the FTS rows of specified nodes with search_documents. @intent Avoids full namespace FTS reloading during incremental update paths.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer updates derived search documents and the configured search backend through one DB handle. @intent provide a transaction-scoped SearchWriter implementation for ingest unit-of-work adapters.

func NewSearchWriter

func NewSearchWriter(db *gorm.DB, backend Backend, logger *slog.Logger) *Writer

NewSearchWriter binds derived search updates to the supplied database handle. @intent construct a search writer that can share an ingest transaction with graph persistence.

func (*Writer) RebuildAll

func (w *Writer) RebuildAll(ctx context.Context) error

RebuildAll refreshes every namespace-scoped search document and rebuilds the backend index. @intent implement the full derived-search refresh required by a graph build. @sideEffect rewrites search documents and the backend index through the bound DB handle.

func (*Writer) RebuildIndex

func (w *Writer) RebuildIndex(ctx context.Context) error

RebuildIndex rebuilds the configured full-text backend after documents refresh. @intent implement the second application maintenance stage without exposing backend or database handles.

func (*Writer) RebuildNodes

func (w *Writer) RebuildNodes(ctx context.Context, nodeIDs []uint) error

RebuildNodes refreshes only the supplied node IDs and updates the matching backend scope. @intent implement the incremental derived-search refresh required by graph updates. @sideEffect rewrites scoped search documents and the backend index through the bound DB handle.

func (*Writer) RefreshDocuments

func (w *Writer) RefreshDocuments(ctx context.Context) (int, error)

RefreshDocuments refreshes derived search documents and returns their count. @intent implement the first application maintenance stage without exposing the database handle.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL