@mastra/pg 0.1.8-alpha.9 → 0.2.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +11 -0
- package/dist/_tsup-dts-rollup.d.cts +5 -0
- package/dist/_tsup-dts-rollup.d.ts +5 -0
- package/dist/index.cjs +43 -0
- package/dist/index.js +43 -0
- package/package.json +2 -2
- package/src/vector/index.test.ts +131 -0
- package/src/vector/index.ts +60 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/pg@0.
|
|
2
|
+
> @mastra/pg@0.2.0-alpha.10 build /home/runner/work/mastra/mastra/stores/pg
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.3.6
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 10654ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.7.3
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.7.3
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 11401ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
21
|
-
[32mESM[39m ⚡️ Build success in
|
|
22
|
-
[32mCJS[39m [1mdist/index.cjs [22m[
|
|
23
|
-
[32mCJS[39m ⚡️ Build success in
|
|
20
|
+
[32mESM[39m [1mdist/index.js [22m[32m34.40 KB[39m
|
|
21
|
+
[32mESM[39m ⚡️ Build success in 1309ms
|
|
22
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m34.80 KB[39m
|
|
23
|
+
[32mCJS[39m ⚡️ Build success in 1311ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 0.2.0-alpha.10
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3de7e06: Added new operations implementations for MastraVector interface methods in pg vector store
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [a910463]
|
|
12
|
+
- @mastra/core@0.5.0-alpha.10
|
|
13
|
+
|
|
3
14
|
## 0.1.8-alpha.9
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -216,6 +216,11 @@ declare class PgVector extends MastraVector {
|
|
|
216
216
|
deleteIndex(indexName: string): Promise<void>;
|
|
217
217
|
truncateIndex(indexName: string): Promise<void>;
|
|
218
218
|
disconnect(): Promise<void>;
|
|
219
|
+
updateIndexById(indexName: string, id: string, update: {
|
|
220
|
+
vector?: number[];
|
|
221
|
+
metadata?: Record<string, any>;
|
|
222
|
+
}): Promise<void>;
|
|
223
|
+
deleteIndexById(indexName: string, id: string): Promise<void>;
|
|
219
224
|
}
|
|
220
225
|
export { PgVector }
|
|
221
226
|
export { PgVector as PgVector_alias_1 }
|
|
@@ -216,6 +216,11 @@ declare class PgVector extends MastraVector {
|
|
|
216
216
|
deleteIndex(indexName: string): Promise<void>;
|
|
217
217
|
truncateIndex(indexName: string): Promise<void>;
|
|
218
218
|
disconnect(): Promise<void>;
|
|
219
|
+
updateIndexById(indexName: string, id: string, update: {
|
|
220
|
+
vector?: number[];
|
|
221
|
+
metadata?: Record<string, any>;
|
|
222
|
+
}): Promise<void>;
|
|
223
|
+
deleteIndexById(indexName: string, id: string): Promise<void>;
|
|
219
224
|
}
|
|
220
225
|
export { PgVector }
|
|
221
226
|
export { PgVector as PgVector_alias_1 }
|
package/dist/index.cjs
CHANGED
|
@@ -589,6 +589,49 @@ var PgVector = class extends vector.MastraVector {
|
|
|
589
589
|
async disconnect() {
|
|
590
590
|
await this.pool.end();
|
|
591
591
|
}
|
|
592
|
+
async updateIndexById(indexName, id, update) {
|
|
593
|
+
if (!update.vector && !update.metadata) {
|
|
594
|
+
throw new Error("No updates provided");
|
|
595
|
+
}
|
|
596
|
+
const client = await this.pool.connect();
|
|
597
|
+
try {
|
|
598
|
+
let updateParts = [];
|
|
599
|
+
let values = [id];
|
|
600
|
+
let valueIndex = 2;
|
|
601
|
+
if (update.vector) {
|
|
602
|
+
updateParts.push(`embedding = $${valueIndex}::vector`);
|
|
603
|
+
values.push(`[${update.vector.join(",")}]`);
|
|
604
|
+
valueIndex++;
|
|
605
|
+
}
|
|
606
|
+
if (update.metadata) {
|
|
607
|
+
updateParts.push(`metadata = $${valueIndex}::jsonb`);
|
|
608
|
+
values.push(JSON.stringify(update.metadata));
|
|
609
|
+
}
|
|
610
|
+
if (updateParts.length === 0) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const query = `
|
|
614
|
+
UPDATE ${indexName}
|
|
615
|
+
SET ${updateParts.join(", ")}
|
|
616
|
+
WHERE vector_id = $1
|
|
617
|
+
`;
|
|
618
|
+
await client.query(query, values);
|
|
619
|
+
} finally {
|
|
620
|
+
client.release();
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
async deleteIndexById(indexName, id) {
|
|
624
|
+
const client = await this.pool.connect();
|
|
625
|
+
try {
|
|
626
|
+
const query = `
|
|
627
|
+
DELETE FROM ${indexName}
|
|
628
|
+
WHERE vector_id = $1
|
|
629
|
+
`;
|
|
630
|
+
await client.query(query, [id]);
|
|
631
|
+
} finally {
|
|
632
|
+
client.release();
|
|
633
|
+
}
|
|
634
|
+
}
|
|
592
635
|
};
|
|
593
636
|
var PostgresStore = class extends storage.MastraStorage {
|
|
594
637
|
db;
|
package/dist/index.js
CHANGED
|
@@ -582,6 +582,49 @@ var PgVector = class extends MastraVector {
|
|
|
582
582
|
async disconnect() {
|
|
583
583
|
await this.pool.end();
|
|
584
584
|
}
|
|
585
|
+
async updateIndexById(indexName, id, update) {
|
|
586
|
+
if (!update.vector && !update.metadata) {
|
|
587
|
+
throw new Error("No updates provided");
|
|
588
|
+
}
|
|
589
|
+
const client = await this.pool.connect();
|
|
590
|
+
try {
|
|
591
|
+
let updateParts = [];
|
|
592
|
+
let values = [id];
|
|
593
|
+
let valueIndex = 2;
|
|
594
|
+
if (update.vector) {
|
|
595
|
+
updateParts.push(`embedding = $${valueIndex}::vector`);
|
|
596
|
+
values.push(`[${update.vector.join(",")}]`);
|
|
597
|
+
valueIndex++;
|
|
598
|
+
}
|
|
599
|
+
if (update.metadata) {
|
|
600
|
+
updateParts.push(`metadata = $${valueIndex}::jsonb`);
|
|
601
|
+
values.push(JSON.stringify(update.metadata));
|
|
602
|
+
}
|
|
603
|
+
if (updateParts.length === 0) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
const query = `
|
|
607
|
+
UPDATE ${indexName}
|
|
608
|
+
SET ${updateParts.join(", ")}
|
|
609
|
+
WHERE vector_id = $1
|
|
610
|
+
`;
|
|
611
|
+
await client.query(query, values);
|
|
612
|
+
} finally {
|
|
613
|
+
client.release();
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
async deleteIndexById(indexName, id) {
|
|
617
|
+
const client = await this.pool.connect();
|
|
618
|
+
try {
|
|
619
|
+
const query = `
|
|
620
|
+
DELETE FROM ${indexName}
|
|
621
|
+
WHERE vector_id = $1
|
|
622
|
+
`;
|
|
623
|
+
await client.query(query, [id]);
|
|
624
|
+
} finally {
|
|
625
|
+
client.release();
|
|
626
|
+
}
|
|
627
|
+
}
|
|
585
628
|
};
|
|
586
629
|
var PostgresStore = class extends MastraStorage {
|
|
587
630
|
db;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/pg",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-alpha.10",
|
|
4
4
|
"description": "Postgres provider for Mastra - includes both vector and db storage capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"pg": "^8.13.1",
|
|
23
23
|
"pg-promise": "^11.5.4",
|
|
24
|
-
"@mastra/core": "^0.5.0-alpha.
|
|
24
|
+
"@mastra/core": "^0.5.0-alpha.10"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@microsoft/api-extractor": "^7.49.2",
|
package/src/vector/index.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { PgVector } from '.';
|
|
4
|
+
import { type QueryResult } from '@mastra/core';
|
|
4
5
|
|
|
5
6
|
describe('PgVector', () => {
|
|
6
7
|
let vectorDB: PgVector;
|
|
@@ -232,6 +233,136 @@ describe('PgVector', () => {
|
|
|
232
233
|
});
|
|
233
234
|
});
|
|
234
235
|
|
|
236
|
+
describe('updates', () => {
|
|
237
|
+
const testVectors = [
|
|
238
|
+
[1, 2, 3],
|
|
239
|
+
[4, 5, 6],
|
|
240
|
+
[7, 8, 9],
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
beforeEach(async () => {
|
|
244
|
+
await vectorDB.createIndex({ indexName: testIndexName, dimension: 3 });
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
afterEach(async () => {
|
|
248
|
+
await vectorDB.deleteIndex(testIndexName);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should update the vector by id', async () => {
|
|
252
|
+
const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
253
|
+
expect(ids).toHaveLength(3);
|
|
254
|
+
|
|
255
|
+
const idToBeUpdated = ids[0];
|
|
256
|
+
const newVector = [1, 2, 3];
|
|
257
|
+
const newMetaData = {
|
|
258
|
+
test: 'updates',
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const update = {
|
|
262
|
+
vector: newVector,
|
|
263
|
+
metadata: newMetaData,
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
await vectorDB.updateIndexById(testIndexName, idToBeUpdated, update);
|
|
267
|
+
|
|
268
|
+
const results: QueryResult[] = await vectorDB.query({
|
|
269
|
+
indexName: testIndexName,
|
|
270
|
+
queryVector: newVector,
|
|
271
|
+
topK: 2,
|
|
272
|
+
includeVector: true,
|
|
273
|
+
});
|
|
274
|
+
expect(results[0]?.id).toBe(idToBeUpdated);
|
|
275
|
+
expect(results[0]?.vector).toEqual(newVector);
|
|
276
|
+
expect(results[0]?.metadata).toEqual(newMetaData);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should only update the metadata by id', async () => {
|
|
280
|
+
const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
281
|
+
expect(ids).toHaveLength(3);
|
|
282
|
+
|
|
283
|
+
const idToBeUpdated = ids[0];
|
|
284
|
+
const newMetaData = {
|
|
285
|
+
test: 'updates',
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const update = {
|
|
289
|
+
metadata: newMetaData,
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
await vectorDB.updateIndexById(testIndexName, idToBeUpdated, update);
|
|
293
|
+
|
|
294
|
+
const results: QueryResult[] = await vectorDB.query({
|
|
295
|
+
indexName: testIndexName,
|
|
296
|
+
queryVector: testVectors[0],
|
|
297
|
+
topK: 2,
|
|
298
|
+
includeVector: true,
|
|
299
|
+
});
|
|
300
|
+
expect(results[0]?.id).toBe(idToBeUpdated);
|
|
301
|
+
expect(results[0]?.vector).toEqual(testVectors[0]);
|
|
302
|
+
expect(results[0]?.metadata).toEqual(newMetaData);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should only update vector embeddings by id', async () => {
|
|
306
|
+
const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
307
|
+
expect(ids).toHaveLength(3);
|
|
308
|
+
|
|
309
|
+
const idToBeUpdated = ids[0];
|
|
310
|
+
const newVector = [1, 2, 3];
|
|
311
|
+
|
|
312
|
+
const update = {
|
|
313
|
+
vector: newVector,
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
await vectorDB.updateIndexById(testIndexName, idToBeUpdated, update);
|
|
317
|
+
|
|
318
|
+
const results: QueryResult[] = await vectorDB.query({
|
|
319
|
+
indexName: testIndexName,
|
|
320
|
+
queryVector: newVector,
|
|
321
|
+
topK: 2,
|
|
322
|
+
includeVector: true,
|
|
323
|
+
});
|
|
324
|
+
expect(results[0]?.id).toBe(idToBeUpdated);
|
|
325
|
+
expect(results[0]?.vector).toEqual(newVector);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('should throw exception when no updates are given', () => {
|
|
329
|
+
expect(vectorDB.updateIndexById(testIndexName, 'id', {})).rejects.toThrow('No updates provided');
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe('deletes', () => {
|
|
334
|
+
const testVectors = [
|
|
335
|
+
[1, 2, 3],
|
|
336
|
+
[4, 5, 6],
|
|
337
|
+
[7, 8, 9],
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
beforeEach(async () => {
|
|
341
|
+
await vectorDB.createIndex({ indexName: testIndexName, dimension: 3 });
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
afterEach(async () => {
|
|
345
|
+
await vectorDB.deleteIndex(testIndexName);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('should delete the vector by id', async () => {
|
|
349
|
+
const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
350
|
+
expect(ids).toHaveLength(3);
|
|
351
|
+
const idToBeDeleted = ids[0];
|
|
352
|
+
|
|
353
|
+
await vectorDB.deleteIndexById(testIndexName, idToBeDeleted);
|
|
354
|
+
|
|
355
|
+
const results: QueryResult[] = await vectorDB.query({
|
|
356
|
+
indexName: testIndexName,
|
|
357
|
+
queryVector: [1.0, 0.0, 0.0],
|
|
358
|
+
topK: 2,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
expect(results).toHaveLength(2);
|
|
362
|
+
expect(results.map(res => res.id)).not.toContain(idToBeDeleted);
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
235
366
|
describe('Basic Query Operations', () => {
|
|
236
367
|
['flat', 'hnsw', 'ivfflat'].forEach(indexType => {
|
|
237
368
|
const indexName = `test_query_2_${indexType}`;
|
package/src/vector/index.ts
CHANGED
|
@@ -426,4 +426,64 @@ export class PgVector extends MastraVector {
|
|
|
426
426
|
async disconnect() {
|
|
427
427
|
await this.pool.end();
|
|
428
428
|
}
|
|
429
|
+
|
|
430
|
+
async updateIndexById(
|
|
431
|
+
indexName: string,
|
|
432
|
+
id: string,
|
|
433
|
+
update: {
|
|
434
|
+
vector?: number[];
|
|
435
|
+
metadata?: Record<string, any>;
|
|
436
|
+
},
|
|
437
|
+
): Promise<void> {
|
|
438
|
+
if (!update.vector && !update.metadata) {
|
|
439
|
+
throw new Error('No updates provided');
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const client = await this.pool.connect();
|
|
443
|
+
try {
|
|
444
|
+
let updateParts = [];
|
|
445
|
+
let values = [id];
|
|
446
|
+
let valueIndex = 2;
|
|
447
|
+
|
|
448
|
+
if (update.vector) {
|
|
449
|
+
updateParts.push(`embedding = $${valueIndex}::vector`);
|
|
450
|
+
values.push(`[${update.vector.join(',')}]`);
|
|
451
|
+
valueIndex++;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (update.metadata) {
|
|
455
|
+
updateParts.push(`metadata = $${valueIndex}::jsonb`);
|
|
456
|
+
values.push(JSON.stringify(update.metadata));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (updateParts.length === 0) {
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// query looks like this:
|
|
464
|
+
// UPDATE table SET embedding = $2::vector, metadata = $3::jsonb WHERE id = $1
|
|
465
|
+
const query = `
|
|
466
|
+
UPDATE ${indexName}
|
|
467
|
+
SET ${updateParts.join(', ')}
|
|
468
|
+
WHERE vector_id = $1
|
|
469
|
+
`;
|
|
470
|
+
|
|
471
|
+
await client.query(query, values);
|
|
472
|
+
} finally {
|
|
473
|
+
client.release();
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async deleteIndexById(indexName: string, id: string): Promise<void> {
|
|
478
|
+
const client = await this.pool.connect();
|
|
479
|
+
try {
|
|
480
|
+
const query = `
|
|
481
|
+
DELETE FROM ${indexName}
|
|
482
|
+
WHERE vector_id = $1
|
|
483
|
+
`;
|
|
484
|
+
await client.query(query, [id]);
|
|
485
|
+
} finally {
|
|
486
|
+
client.release();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
429
489
|
}
|