Skip to content

Repository files navigation

pgvector-go

pgvector support for Go

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

pgvector-go 0.4.0 was recently released - see how to upgrade

Build Status

Getting Started

Follow the instructions for your database library:

Or check out some examples:

pgx

Run:

go get github.com/pgvector/pgvector-go
go get github.com/pgvector/pgvector-go/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 {
returnpgxvec.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

Run:

go get github.com/pgvector/pgvector-go

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

typeItemstruct {
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

varitems []Itemerr:=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

Run:

go get github.com/pgvector/pgvector-go

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

typeItemstruct {
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

varitems []Itemerr:=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)
returnerr
}

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Ent

Run:

go get github.com/pgvector/pgvector-go
go get github.com/pgvector/pgvector-go/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

Run:

go get github.com/pgvector/pgvector-go

Import the package

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

Enable the extension

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

Add a vector column

typeItemstruct {
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

varitems []Itemdb.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)")
// ordb.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

Run:

go get github.com/pgvector/pgvector-go

Import the package

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

Enable the extension

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

Add a vector column

typeItemstruct {
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

varitems []Itemdb.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)")
// ordb.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()

Upgrading

0.4.0

For pgx, run:

go get github.com/pgvector/pgvector-go
go get github.com/pgvector/pgvector-go/pgx

For Ent, run:

go get github.com/pgvector/pgvector-go
go get github.com/pgvector/pgvector-go/ent

For other database libraries, run:

go get github.com/pgvector/pgvector-go

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
cdtest
go mod tidy
go generate ./ent
go mod tidy
go test -v

To run an example:

createdb pgvector_example
cd examples
go mod tidy
go run ./loading

About

pgvector support for Go

Resources

Security policy

Stars

348 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages