npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

pgvector

v0.2.0

Published

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

Downloads

210,272

Readme

pgvector-node

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

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

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

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

Register the type for a client

import pgvector from 'pgvector/pg';

await pgvector.registerType(client);

or a pool

pool.on('connect', async function (client) {
  await pgvector.registerType(client);
});

Create a table

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

Insert a vector

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

Get the nearest neighbors to a vector

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

Add an approximate index

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

import pgvector from 'pgvector/knex';

Enable the extension

await knex.schema.enableExtension('vector');

Create a table

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

Insert vectors

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

Get the nearest neighbors to a vector

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

Also supports maxInnerProduct and cosineDistance

Add an approximate index

await knex.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

import pgvector from 'pgvector/objection';

Enable the extension

await knex.schema.enableExtension('vector');

Create a table

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

Insert vectors

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

Get the nearest neighbors to a vector

import { l2Distance } from 'pgvector/objection';

const items = await Item.query()
  .orderBy(l2Distance('embedding', [1, 2, 3]))
  .limit(5);

Also supports maxInnerProduct and cosineDistance

Add an approximate index

await knex.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

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

Create a table

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

Insert vectors

import pgvector from 'pgvector/kysely';

const newItems = [
  {embedding: pgvector.toSql([1, 2, 3])},
  {embedding: pgvector.toSql([4, 5, 6])}
];
await db.insertInto('items').values(newItems).execute();

Get the nearest neighbors to a vector

import { l2Distance } from 'pgvector/kysely';

const items = await db.selectFrom('items')
  .selectAll()
  .orderBy(l2Distance('embedding', [1, 2, 3]))
  .limit(5)
  .execute();

Also supports maxInnerProduct and cosineDistance

Add an approximate index

await db.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

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

Register the type

import { Sequelize } from 'sequelize';
import pgvector from 'pgvector/sequelize';

pgvector.registerType(Sequelize);

Add a vector field

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

Insert a vector

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

Get the nearest neighbors to a vector

const items = await Item.findAll({
  order: l2Distance('embedding', [1, 1, 1], sequelize),
  limit: 5
});

Also supports maxInnerProduct and cosineDistance

Add an approximate index

const Item = 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

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

Register the type

import pgpromise from 'pg-promise';
import pgvector from 'pgvector/pg-promise';

const initOptions = {
  async connect(e) {
    await pgvector.registerType(e.client);
  }
};
const pgp = pgpromise(initOptions);

Create a table

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

Insert a vector

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

Get the nearest neighbors to a vector

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

Add an approximate index

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

import pgvector from 'pgvector';

Add the extension to the schema

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["postgresqlExtensions"]
}

datasource db {
  provider   = "postgresql"
  url        = env("DATABASE_URL")
  extensions = [vector]
}

Add a vector column to the schema

model Item {
  id        Int                       @id @default(autoincrement())
  embedding Unsupported("vector(3)")?
}

Insert a vector

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

Get the nearest neighbors to a vector

const embedding = pgvector.toSql([1, 2, 3])
const items = await prisma.$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

import pgvector from 'pgvector';

Enable the extension

await sql`CREATE EXTENSION IF NOT EXISTS vector`;

Create a table

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

Insert vectors

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

Get the nearest neighbors to a vector

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

Add an approximate index

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

import pgvector from 'pgvector';

Enable the extension

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

Create a table

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

Insert a vector

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

Get the nearest neighbors to a vector

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

Add an approximate index

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

import pgvector from 'pgvector';

Enable the extension

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

Create a table

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

Define an entity

@Entity()
class Item {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  embedding: string
}

Insert a vector

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

Get the nearest neighbors to a vector

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

See a full example

MikroORM

Enable the extension

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

Define an entity

import { VectorType } from 'pgvector/mikro-orm';

@Entity()
class Item {
  @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';

const items = await em.createQueryBuilder(Item)
  .orderBy({[l2Distance('embedding', [1, 2, 3])]: 'ASC'})
  .limit(5)
  .getResult();

Also supports maxInnerProduct and cosineDistance

See a full example

Drizzle ORM

Drizzle ORM 0.31.0+ has built-in support for pgvector :tada:

Enable the extension

await client`CREATE EXTENSION IF NOT EXISTS vector`;

Add a vector field

import { vector } from 'drizzle-orm/pg-core';

const items = pgTable('items', {
  id: serial('id').primaryKey(),
  embedding: vector('embedding', {dimensions: 3})
});

Also supports halfvec, bit, and sparsevec

Insert vectors

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

Get the nearest neighbors to a vector

import { l2Distance } from 'drizzle-orm';

const allItems = await db.select()
  .from(items)
  .orderBy(l2Distance(items.embedding, [1, 2, 3]))
  .limit(5);

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

See a full example

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 migrate dev
npm test