Skip to content

pgvector support for Node.js, Deno, and Bun (and TypeScript)

License

Notifications You must be signed in to change notification settings

pgvector/pgvector-node

Repository files navigation

pgvector-node

pgvector support for Node.js, Deno, and Bun (and TypeScript)

Supports node-postgres, Knex.js, Objection.js, Kysely, Sequelize, pg-promise, Prisma, Postgres.js, Slonik, TypeORM, MikroORM, Drizzle ORM, and Bun SQL

Build Status

Installation

Run:

npm install pgvector

And follow the instructions for your database library:

Or check out some examples:

node-postgres

Enable the extension

awaitclient.query('CREATE EXTENSION IF NOT EXISTS vector');

Register the types for a client

importpgvectorfrom'pgvector/pg';awaitpgvector.registerTypes(client);

or a pool

pool.on('connect',asyncfunction(client){awaitpgvector.registerTypes(client);});

Create a table

awaitclient.query('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))');

Insert a vector

awaitclient.query('INSERT INTO items (embedding) VALUES ($1)',[pgvector.toSql([1,2,3])]);

Get the nearest neighbors to a vector

constresult=awaitclient.query('SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5',[pgvector.toSql([1,2,3])]);

Add an approximate index

awaitclient.query('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)');// orawaitclient.query('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

Knex.js

Import the library

importpgvectorfrom'pgvector/knex';

Enable the extension

awaitknex.schema.createExtensionIfNotExists('vector');

Create a table

awaitknex.schema.createTable('items',(table)=>{table.increments('id');table.vector('embedding',3);});

Insert vectors

constnewItems=[{embedding: pgvector.toSql([1,2,3])},{embedding: pgvector.toSql([4,5,6])}];awaitknex('items').insert(newItems);

Get the nearest neighbors to a vector

constitems=awaitknex('items').orderBy(knex.l2Distance('embedding',[1,2,3])).limit(5);

Also supports maxInnerProduct, cosineDistance, l1Distance, hammingDistance, and jaccardDistance

Add an approximate index

awaitknex.schema.alterTable('items',function(table){table.index(knex.raw('embedding vector_l2_ops'),'index_name','hnsw');});

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Objection.js

Import the library

importpgvectorfrom'pgvector/objection';

Enable the extension

awaitknex.schema.createExtensionIfNotExists('vector');

Create a table

awaitknex.schema.createTable('items',(table)=>{table.increments('id');table.vector('embedding',3);});

Insert vectors

constnewItems=[{embedding: pgvector.toSql([1,2,3])},{embedding: pgvector.toSql([4,5,6])}];awaitItem.query().insert(newItems);

Get the nearest neighbors to a vector

import{l2Distance}from'pgvector/objection';constitems=awaitItem.query().orderBy(l2Distance('embedding',[1,2,3])).limit(5);

Also supports maxInnerProduct, cosineDistance, l1Distance, hammingDistance, and jaccardDistance

Add an approximate index

awaitknex.schema.alterTable('items',function(table){table.index(knex.raw('embedding vector_l2_ops'),'index_name','hnsw');});

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Kysely

Enable the extension

awaitsql`CREATE EXTENSION IF NOT EXISTS vector`.execute(db);

Create a table

awaitdb.schema.createTable('items').addColumn('id','serial',(cb)=>cb.primaryKey()).addColumn('embedding',sql`vector(3)`).execute();

Insert vectors

importpgvectorfrom'pgvector/kysely';constnewItems=[{embedding: pgvector.toSql([1,2,3])},{embedding: pgvector.toSql([4,5,6])}];awaitdb.insertInto('items').values(newItems).execute();

Get the nearest neighbors to a vector

import{l2Distance}from'pgvector/kysely';constitems=awaitdb.selectFrom('items').selectAll().orderBy(l2Distance('embedding',[1,2,3])).limit(5).execute();

Also supports maxInnerProduct, cosineDistance, l1Distance, hammingDistance, and jaccardDistance

Get items within a certain distance

constitems=awaitdb.selectFrom('items').selectAll().where(l2Distance('embedding',[1,2,3]),'<',5).execute();

Add an approximate index

awaitdb.schema.createIndex('index_name').on('items').using('hnsw').expression(sql`embedding vector_l2_ops`).execute();

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Sequelize

Enable the extension

awaitsequelize.query('CREATE EXTENSION IF NOT EXISTS vector');

Register the types

import{Sequelize}from'sequelize';importpgvectorfrom'pgvector/sequelize';pgvector.registerTypes(Sequelize);

Add a vector field

constItem=sequelize.define('Item',{embedding: {type: DataTypes.VECTOR(3)}}, ...);

Insert a vector

awaitItem.create({embedding: [1,2,3]});

Get the nearest neighbors to a vector

import{l2Distance}from'pgvector/sequelize';constitems=awaitItem.findAll({order: l2Distance('embedding',[1,1,1],sequelize),limit: 5});

Also supports maxInnerProduct, cosineDistance, l1Distance, hammingDistance, and jaccardDistance

Add an approximate index

constItem=sequelize.define('Item', ...,{indexes: [{fields: ['embedding'],using: 'hnsw',operator: 'vector_l2_ops'}]});

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

pg-promise

Enable the extension

awaitdb.none('CREATE EXTENSION IF NOT EXISTS vector');

Register the types

importpgpromisefrom'pg-promise';importpgvectorfrom'pgvector/pg-promise';constinitOptions={asyncconnect(e){awaitpgvector.registerTypes(e.client);}};constpgp=pgpromise(initOptions);

Create a table

awaitdb.none('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))');

Insert a vector

awaitdb.none('INSERT INTO items (embedding) VALUES ($1)',[pgvector.toSql([1,2,3])]);

Get the nearest neighbors to a vector

constresult=awaitdb.any('SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5',[pgvector.toSql([1,2,3])]);

Add an approximate index

awaitdb.none('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)');// orawaitdb.none('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

Prisma

Note: prisma migrate dev does not support pgvector indexes

Import the library

importpgvectorfrom'pgvector';

Add the extension to the schema

generatorclient{provider="prisma-client"previewFeatures=["postgresqlExtensions"]}datasourcedb{provider="postgresql"extensions=[vector]}

Add a vector column to the schema

modelItem{idInt@id@default(autoincrement())embeddingUnsupported("vector(3)")?}

Insert a vector

constembedding=pgvector.toSql([1,2,3])awaitprisma.$executeRaw`INSERT INTO items (embedding) VALUES (${embedding}::vector)`

Get the nearest neighbors to a vector

constembedding=pgvector.toSql([1,2,3])constitems=awaitprisma.$queryRaw`SELECT id, embedding::text FROM items ORDER BY embedding <-> ${embedding}::vector LIMIT 5`

See a full example (and the schema)

Postgres.js

Import the library

importpgvectorfrom'pgvector';

Enable the extension

awaitsql`CREATE EXTENSION IF NOT EXISTS vector`;

Create a table

awaitsql`CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))`;

Insert vectors

constnewItems=[{embedding: pgvector.toSql([1,2,3])},{embedding: pgvector.toSql([4,5,6])}];awaitsql`INSERT INTO items ${sql(newItems,'embedding')}`;

Get the nearest neighbors to a vector

constembedding=pgvector.toSql([1,2,3]);constitems=awaitsql`SELECT * FROM items ORDER BY embedding <-> ${embedding} LIMIT 5`;

Add an approximate index

awaitsql`CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)`;// orawaitsql`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

Slonik

Import the library

importpgvectorfrom'pgvector';

Enable the extension

awaitpool.query(sql.unsafe`CREATE EXTENSION IF NOT EXISTS vector`);

Create a table

awaitpool.query(sql.unsafe`CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3))`);

Insert a vector

constembedding=pgvector.toSql([1,2,3]);awaitpool.query(sql.unsafe`INSERT INTO items (embedding) VALUES (${embedding})`);

Get the nearest neighbors to a vector

constembedding=pgvector.toSql([1,2,3]);constitems=awaitpool.query(sql.unsafe`SELECT * FROM items ORDER BY embedding <-> ${embedding} LIMIT 5`);

Add an approximate index

awaitpool.query(sql.unsafe`CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)`);// orawaitpool.query(sql.unsafe`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

TypeORM

Import the library

importpgvectorfrom'pgvector';

Enable the extension

awaitAppDataSource.query('CREATE EXTENSION IF NOT EXISTS vector');

Create a table

awaitAppDataSource.query('CREATE TABLE item (id bigserial PRIMARY KEY, embedding vector(3))');

Define an entity

@Entity()classItem{ @PrimaryGeneratedColumn()id: number @Column()embedding: string}

Insert a vector

constitemRepository=AppDataSource.getRepository(Item);awaititemRepository.save({embedding: pgvector.toSql([1,2,3])});

Get the nearest neighbors to a vector

constitems=awaititemRepository.createQueryBuilder('item').orderBy('embedding <-> :embedding').setParameters({embedding: pgvector.toSql([1,2,3])}).limit(5).getMany();

See a full example

MikroORM

Enable the extension

awaitem.execute('CREATE EXTENSION IF NOT EXISTS vector');

Define an entity

import{VectorType}from'pgvector/mikro-orm'; @Entity()classItem{ @PrimaryKey()id: number; @Property({type: VectorType})embedding: number[];}

Insert a vector

em.create(Item,{embedding: [1,2,3]});

Get the nearest neighbors to a vector

import{l2Distance}from'pgvector/mikro-orm';constitems=awaitem.createQueryBuilder(Item).orderBy({[l2Distance('embedding',[1,2,3])]: 'ASC'}).limit(5).getResult();

Also supports maxInnerProduct, cosineDistance, l1Distance, hammingDistance, and jaccardDistance

See a full example

Drizzle ORM

Drizzle ORM 0.31.0+ has built-in support for pgvector 🎉

Enable the extension

awaitclient`CREATE EXTENSION IF NOT EXISTS vector`;

Add a vector field

import{vector}from'drizzle-orm/pg-core';constitems=pgTable('items',{id: serial('id').primaryKey(),embedding: vector('embedding',{dimensions: 3})});

Also supports halfvec, bit, and sparsevec

Insert vectors

constnewItems=[{embedding: [1,2,3]},{embedding: [4,5,6]}];awaitdb.insert(items).values(newItems);

Get the nearest neighbors to a vector

import{l2Distance}from'drizzle-orm';constallItems=awaitdb.select().from(items).orderBy(l2Distance(items.embedding,[1,2,3])).limit(5);

Also supports innerProduct, cosineDistance, l1Distance, hammingDistance, and jaccardDistance

See a full example

Bun SQL

Import the library

importpgvectorfrom'pgvector';

Enable the extension

awaitsql`CREATE EXTENSION IF NOT EXISTS vector`;

Create a table

awaitsql`CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))`;

Insert vectors

constnewItems=[{embedding: pgvector.toSql([1,2,3])},{embedding: pgvector.toSql([4,5,6])}];awaitsql`INSERT INTO items ${sql(newItems)}`;

Get the nearest neighbors to a vector

constembedding=pgvector.toSql([1,2,3]);constitems=awaitsql`SELECT * FROM items ORDER BY embedding <-> ${embedding} LIMIT 5`.values();

Add an approximate index

awaitsql`CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)`;// orawaitsql`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

Sparse Vectors

Create a sparse vector from an array

constvec=newSparseVector([1,0,2,0,3,0]);

Or a map of non-zero elements

constvec=newSparseVector({0: 1,2: 2,4: 3},6);// orconstmap=newMap();map.set(0,1);map.set(2,2);map.set(4,3);constvec=newSparseVector(map,6);

Note: Indices start at 0

Get the number of dimensions

constdim=vec.dimensions;

Get the indices of non-zero elements

constindices=vec.indices;

Get the values of non-zero elements

constvalues=vec.values;

Get an array

constarr=vec.toArray();

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-node.git cd pgvector-node npm install createdb pgvector_node_test npx prisma generate npx prisma migrate dev npm test

To run an example:

cd examples/loading npm install createdb pgvector_example node example.js

About

pgvector support for Node.js, Deno, and Bun (and TypeScript)

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published