Skip to content

Commit

Permalink
Added Objection.js example
Browse files Browse the repository at this point in the history
  • Loading branch information
ankane committed Dec 13, 2023
1 parent a34855a commit 22c16d3
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[pgvector](https:/pgvector/pgvector) support for Node.js and Bun (and TypeScript)

Supports [node-postgres](https:/brianc/node-postgres), [Knex.js](https:/knex/knex), [Sequelize](https:/sequelize/sequelize), [pg-promise](https:/vitaly-t/pg-promise), [Prisma](https:/prisma/prisma), [Postgres.js](https:/porsager/postgres), [TypeORM](https:/typeorm/typeorm), [MikroORM](https:/mikro-orm/mikro-orm), and [Drizzle ORM](https:/drizzle-team/drizzle-orm)
Supports [node-postgres](https:/brianc/node-postgres), [Knex.js](https:/knex/knex), [Objection.js](https:/vincit/objection.js), [Sequelize](https:/sequelize/sequelize), [pg-promise](https:/vitaly-t/pg-promise), [Prisma](https:/prisma/prisma), [Postgres.js](https:/porsager/postgres), [TypeORM](https:/typeorm/typeorm), [MikroORM](https:/mikro-orm/mikro-orm), and [Drizzle ORM](https:/drizzle-team/drizzle-orm)

[![Build Status](https:/pgvector/pgvector-node/workflows/build/badge.svg?branch=master)](https:/pgvector/pgvector-node/actions)

Expand All @@ -18,6 +18,7 @@ And follow the instructions for your database library:

- [node-postgres](#node-postgres)
- [Knex.js](#knexjs)
- [Objection.js](#objectionjs)
- [Sequelize](#sequelize)
- [pg-promise](#pg-promise)
- [Prisma](#prisma)
Expand Down Expand Up @@ -142,6 +143,61 @@ Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distanc

See a [full example](tests/knex/index.test.mjs)

## Objection.js

Import the library

```javascript
import pgvector from 'pgvector/knex';
```

Enable the extension

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

Create a table

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

Insert vectors

```javascript
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

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

Also supports `maxInnerProduct` and `cosineDistance`

Add an approximate index

```javascript
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](tests/objection/index.test.mjs)

## Sequelize

Enable the extension
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"drizzle-orm": "^0.29.1",
"jest": "^29.5.0",
"knex": "^3.1.0",
"objection": "^3.1.3",
"pg": "^8.6.0",
"pg-promise": "^11.4.3",
"postgres": "^3.3.4",
Expand Down
59 changes: 59 additions & 0 deletions tests/objection/index.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Knex from 'knex';
import { Model } from 'objection';
import pgvector from 'pgvector/knex';

test('example', async () => {
const knex = Knex({
client: 'pg',
connection: {database: 'pgvector_node_test'}
});

Model.knex(knex);

class Item extends Model {
static get tableName() {
return 'objection_items';
}
}

await knex.schema.enableExtension('vector');
await knex.schema.dropTableIfExists('objection_items');
await knex.schema.createTable('objection_items', (table) => {
table.increments('id');
table.vector('embedding', {dimensions: 3});
});

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

// L2 distance
let items = await Item.query()
.orderBy(knex.l2Distance('embedding', [1, 1, 1]))
.limit(5);
expect(items.map(v => v.id)).toStrictEqual([1, 3, 2]);
expect(pgvector.fromSql(items[0].embedding)).toStrictEqual([1, 1, 1]);
expect(pgvector.fromSql(items[1].embedding)).toStrictEqual([1, 1, 2]);
expect(pgvector.fromSql(items[2].embedding)).toStrictEqual([2, 2, 2]);

// max inner product
items = await Item.query()
.orderBy(knex.maxInnerProduct('embedding', [1, 1, 1]))
.limit(5);
expect(items.map(v => v.id)).toStrictEqual([2, 3, 1]);

// cosine distance
items = await Item.query()
.orderBy(knex.cosineDistance('embedding', [1, 1, 1]))
.limit(5);
expect(items[2].id).toEqual(3);

await knex.schema.alterTable('objection_items', function(table) {
table.index(knex.raw('embedding vector_l2_ops'), 'objection_items_embedding_idx', 'hnsw');
});

await knex.destroy();
});

0 comments on commit 22c16d3

Please sign in to comment.