Skip to content

pgvector/pgvector-go

Repository files navigation

pgvector-go

pgvector support for Go

Supports pgx, pg, Bun, Ent, GORM, and sqlx

Build Status

Getting Started

Run:

go get github.com/pgvector/pgvector-go

And follow the instructions for your database library:

Or check out some examples:

pgx

Import the packages

import ( "github.com/pgvector/pgvector-go" pgxvec "github.com/pgvector/pgvector-go/pgx" )

Enable the extension

_, err := conn.Exec(ctx, "CREATE EXTENSION IF NOT EXISTS vector")

Register the types with the connection

err := pgxvec.RegisterTypes(ctx, conn)

or the pool

config.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { return pgxvec.RegisterTypes(ctx, conn) }

Create a table

_, err := conn.Exec(ctx, "CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))")

Insert a vector

_, err := conn.Exec(ctx, "INSERT INTO items (embedding) VALUES ($1)", pgvector.NewVector([]float32{1, 2, 3}))

Get the nearest neighbors to a vector

rows, err := conn.Query(ctx, "SELECT id FROM items ORDER BY embedding <-> $1 LIMIT 5", pgvector.NewVector([]float32{1, 2, 3}))

Add an approximate index

_, err := conn.Exec(ctx, "CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)") // or _, err := conn.Exec(ctx, "CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)")

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

pg

Import the package

import "github.com/pgvector/pgvector-go"

Enable the extension

_, err := db.Exec("CREATE EXTENSION IF NOT EXISTS vector")

Add a vector column

type Item struct { Embedding pgvector.Vector `pg:"type:vector(3)"` }

Insert a vector

item := Item{ Embedding: pgvector.NewVector([]float32{1, 2, 3}), } _, err := db.Model(&item).Insert()

Get the nearest neighbors to a vector

var items []Item err := db.Model(&items). OrderExpr("embedding <-> ?", pgvector.NewVector([]float32{1, 2, 3})). Limit(5). Select()

Add an approximate index

_, err := conn.Exec(ctx, "CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)") // or _, err := conn.Exec(ctx, "CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)")

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Bun

Import the package

import "github.com/pgvector/pgvector-go"

Enable the extension

_, err := db.Exec("CREATE EXTENSION IF NOT EXISTS vector")

Add a vector column

type Item struct { Embedding pgvector.Vector `bun:"type:vector(3)"` }

Insert a vector

item := Item{ Embedding: pgvector.NewVector([]float32{1, 2, 3}), } _, err := db.NewInsert().Model(&item).Exec(ctx)

Get the nearest neighbors to a vector

var items []Item err := db.NewSelect(). Model(&items). OrderExpr("embedding <-> ?", pgvector.NewVector([]float32{1, 2, 3})). Limit(5). Scan(ctx)

Add an approximate index

var _ bun.AfterCreateTableHook = (*Item)(nil) func (*Item) AfterCreateTable(ctx context.Context, query *bun.CreateTableQuery) error { _, err := query.DB().NewCreateIndex(). Model((*Item)(nil)). Index("items_embedding_idx"). ColumnExpr("embedding vector_l2_ops"). Using("hnsw"). Exec(ctx) return err }

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Ent

Import the package

import ( "github.com/pgvector/pgvector-go" entvec "github.com/pgvector/pgvector-go/ent" )

Enable the extension (requires the sql/execquery feature)

_, err := client.ExecContext(ctx, "CREATE EXTENSION IF NOT EXISTS vector")

Add a vector column

func (Item) Fields() []ent.Field { return []ent.Field{ field.Other("embedding", pgvector.Vector{}). SchemaType(map[string]string{ dialect.Postgres: "vector(3)", }), } }

Insert a vector

_, err := client.Item. Create(). SetEmbedding(pgvector.NewVector([]float32{1, 2, 3})). Save(ctx)

Get the nearest neighbors to a vector

items, err := client.Item. Query(). Order(func(s *sql.Selector) { s.OrderExpr(entvec.L2Distance("embedding", pgvector.NewVector([]float32{1, 2, 3}))) }). Limit(5). All(ctx)

Also supports MaxInnerProduct, CosineDistance, L1Distance, HammingDistance, and JaccardDistance

Add an approximate index

func (Item) Indexes() []ent.Index { return []ent.Index{ index.Fields("embedding"). Annotations( entsql.IndexType("hnsw"), entsql.OpClass("vector_l2_ops"), ), } }

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

GORM

Import the package

import "github.com/pgvector/pgvector-go"

Enable the extension

db.Exec("CREATE EXTENSION IF NOT EXISTS vector")

Add a vector column

type Item struct { Embedding pgvector.Vector `gorm:"type:vector(3)"` }

Insert a vector

item := Item{ Embedding: pgvector.NewVector([]float32{1, 2, 3}), } result := db.Create(&item)

Get the nearest neighbors to a vector

var items []Item db.Clauses(clause.OrderBy{ Expression: clause.Expr{SQL: "embedding <-> ?", Vars: []interface{}{pgvector.NewVector([]float32{1, 1, 1})}}, }).Limit(5).Find(&items)

Add an approximate index

db.Exec("CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)") // or db.Exec("CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)")

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

sqlx

Import the package

import "github.com/pgvector/pgvector-go"

Enable the extension

db.MustExec("CREATE EXTENSION IF NOT EXISTS vector")

Add a vector column

type Item struct { Embedding pgvector.Vector }

Insert a vector

item := Item{ Embedding: pgvector.NewVector([]float32{1, 2, 3}), } _, err := db.NamedExec(`INSERT INTO items (embedding) VALUES (:embedding)`, item)

Get the nearest neighbors to a vector

var items []Item db.Select(&items, "SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5", pgvector.NewVector([]float32{1, 1, 1}))

Add an approximate index

db.MustExec("CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)") // or db.MustExec("CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)")

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Reference

Vectors

Create a vector from a slice

vec := pgvector.NewVector([]float32{1, 2, 3})

Get a slice

slice := vec.Slice()

Half Vectors

Create a half vector from a slice

vec := pgvector.NewHalfVector([]float32{1, 2, 3})

Get a slice

slice := vec.Slice()

Sparse Vectors

Create a sparse vector from a slice

vec := pgvector.NewSparseVector([]float32{1, 0, 2, 0, 3, 0})

Or a map of non-zero elements

elements := map[int32]float32{0: 1, 2: 2, 4: 3} vec := pgvector.NewSparseVectorFromMap(elements, 6)

Note: Indices start at 0

Get the number of dimensions

dim := vec.Dimensions()

Get the indices of non-zero elements

indices := vec.Indices()

Get the values of non-zero elements

values := vec.Values()

Get a slice

slice := vec.Slice()

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development:

git clone https://github.com/pgvector/pgvector-go.git cd pgvector-go go mod tidy createdb pgvector_go_test go generate ./test/ent go test -v

To run an example:

createdb pgvector_example go run ./examples/loading

About

pgvector support for Go

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages