Skip to content

gabisonia/go-vectorstore

Repository files navigation

go-vectorstore

Go Reference Latest Release Go Version License: MIT

A lightweight Go vector-store library inspired by Microsoft.Extensions.VectorData.

MVP scope:

  • Go 1.24.x
  • Postgres + pgvector
  • Record-based core API with optional typed codec wrapper

This library can be used to build retrieval systems such as:

  • semantic search
  • RAG pipelines (retrieve from vector DB, then generate with an LLM)
  • context-aware assistants grounded on your own data

Requirements

  • Go 1.24.x
  • PostgreSQL 16+ with pgvector extension
  • Docker (optional, for integration tests and sample compose flows)

Project layout

  • vectordata: backend-agnostic core interfaces, record model, filters, typed wrapper
  • stores/postgres: Postgres implementation with pgxpool
  • samples: runnable demos (see samples/README.md)
  • docs: architecture and implementation notes

Install

go get github.com/gabisonia/go-vectorstore

Quick Start (Local)

  1. Start local Postgres + pgvector from the repository root:
docker compose up -d postgres
  1. Export your OpenAI key and run the semantic sample:
export OPENAI_API_KEY=your_key_here
go get github.com/gabisonia/go-vectorstore/vectordata@latest
go run ./samples/semantic-search -q "how can I reduce cloud costs?"
  1. Stop local services when done:
docker compose down

Core API Walkthrough

package main

import (
    "context"
    "fmt"

    "github.com/gabisonia/go-vectorstore/stores/postgres"
    "github.com/gabisonia/go-vectorstore/vectordata"
    "github.com/jackc/pgx/v5/pgxpool"
)

func main() {
    ctx := context.Background()
    pool, err := pgxpool.New(ctx, "postgres://postgres:postgres@localhost:54329/vectorstore_test?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer pool.Close()

    store, err := postgres.NewVectorStore(pool, postgres.DefaultStoreOptions())
    if err != nil {
        panic(err)
    }

    collection, err := store.EnsureCollection(ctx, vectordata.CollectionSpec{
        Name:      "docs",
        Dimension: 3,
        Metric:    vectordata.DistanceCosine,
        Mode:      vectordata.EnsureStrict,
    })
    if err != nil {
        panic(err)
    }

    records := []vectordata.Record{
        {
            ID:       "doc-1",
            Vector:   []float32{0.1, 0.2, 0.3},
            Metadata: map[string]any{"category": "news", "rank": 10},
        },
        {
            ID:       "doc-2",
            Vector:   []float32{0.2, 0.1, 0.2},
            Metadata: map[string]any{"category": "blog", "rank": 5},
        },
    }
    if err := collection.Upsert(ctx, records); err != nil {
        panic(err)
    }

    if err := collection.EnsureIndexes(ctx, vectordata.IndexOptions{
        Vector: &vectordata.VectorIndexOptions{
            Method: vectordata.IndexMethodHNSW,
            Metric: vectordata.DistanceCosine,
            HNSW: vectordata.HNSWOptions{
                M:              16,
                EfConstruction: 64,
            },
        },
        Metadata: &vectordata.MetadataIndexOptions{UsePathOps: true},
    }); err != nil {
        panic(err)
    }

    filter := vectordata.And(
        vectordata.Eq(vectordata.Metadata("category"), "news"),
        vectordata.Gt(vectordata.Metadata("rank"), 6),
    )

    results, err := collection.SearchByVector(
        ctx,
        []float32{0.1, 0.2, 0.25},
        5,
        vectordata.SearchOptions{Filter: filter},
    )
    if err != nil {
        panic(err)
    }

    for _, r := range results {
        fmt.Printf("id=%s score=%.4f distance=%.4f\n", r.Record.ID, r.Score, r.Distance)
    }
}

Search Options

SearchByVector supports filtering, thresholding, and projection control.

threshold := 0.35
projection := &vectordata.Projection{
    IncludeMetadata: true,
    IncludeContent:  true,
    IncludeVector:   false,
}

results, err := collection.SearchByVector(ctx, queryVector, 10, vectordata.SearchOptions{
    Filter:     vectordata.Eq(vectordata.Metadata("category"), "backend"),
    Threshold:  &threshold,
    Projection: projection,
})

If Projection is nil, the default projection includes Metadata and Content, but not Vector.

Store Options

store, err := postgres.NewVectorStore(pool, postgres.StoreOptions{
    Schema:          "public",
    EnsureExtension: true,
    StrictByDefault: true,
})
  • Schema: SQL schema for collection tables
  • EnsureExtension: auto-runs CREATE EXTENSION IF NOT EXISTS vector
  • StrictByDefault: default ensure mode when CollectionSpec.Mode is not set

Integration tests

go test -tags=integration ./...

Unit tests run with:

go test ./...

Notes:

  • Integration tests start Postgres/pgvector automatically via Testcontainers
  • Docker daemon must be available when running integration tests
  • Optional override: set PGVECTOR_TEST_DSN to use an existing Postgres instance instead of starting a container

Docker Compose (optional)

docker-compose.yml at the repository root is kept for manual local runs.

  • Use root docker-compose.yml when you want a persistent local Postgres+pgvector instance outside tests
  • Use Testcontainers (go test -tags=integration ./...) for integration tests
  • Sample apps have their own compose files at samples/semantic-search/docker-compose.yml and samples/ragrimosa/docker-compose.yml
  • Sample Dockerfiles use golang:1.24-alpine to match the repo Go version (1.24.x)

Release Automation

GitHub Actions workflows are configured for:

  • CI on pushes/PRs (.github/workflows/ci.yml)
  • release publishing (.github/workflows/release.yml)

Release options:

  1. Manual (recommended): run Release workflow via GitHub UI with version input (0.3.0 or v0.3.0).
  2. Tag-driven: push a semver tag and the workflow publishes release notes automatically:
VERSION="$(cat VERSION)"
git tag "v${VERSION}"
git push origin "v${VERSION}"

Samples

  • Overview and entry points: samples/README.md
  • Semantic search sample app: samples/semantic-search
  • RAG sample app (RAGrimosa): samples/ragrimosa

Documentation

License

This project is licensed under the MIT License.

About

A lightweight Go vector-store library inspired by Microsoft.Extensions.VectorData

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors