@mastra/pg 1.0.0-beta.1 → 1.0.0-beta.2
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/CHANGELOG.md +9 -0
- package/README.md +3 -0
- package/dist/index.cjs +286 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +286 -14
- package/dist/index.js.map +1 -1
- package/dist/vector/index.d.ts +11 -3
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts +4 -0
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Add new deleteVectors, updateVector by filter ([#10408](https://github.com/mastra-ai/mastra/pull/10408))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`21a15de`](https://github.com/mastra-ai/mastra/commit/21a15de369fe82aac26bb642ed7be73505475e8b), [`feb7ee4`](https://github.com/mastra-ai/mastra/commit/feb7ee4d09a75edb46c6669a3beaceec78811747), [`b0e2ea5`](https://github.com/mastra-ai/mastra/commit/b0e2ea5b52c40fae438b9e2f7baee6f0f89c5442), [`c456e01`](https://github.com/mastra-ai/mastra/commit/c456e0149e3c176afcefdbd9bb1d2c5917723725), [`ab035c2`](https://github.com/mastra-ai/mastra/commit/ab035c2ef6d8cc7bb25f06f1a38508bd9e6f126b), [`1a46a56`](https://github.com/mastra-ai/mastra/commit/1a46a566f45a3fcbadc1cf36bf86d351f264bfa3), [`3cf540b`](https://github.com/mastra-ai/mastra/commit/3cf540b9fbfea8f4fc8d3a2319a4e6c0b0cbfd52), [`1c6ce51`](https://github.com/mastra-ai/mastra/commit/1c6ce51f875915ab57fd36873623013699a2a65d), [`898a972`](https://github.com/mastra-ai/mastra/commit/898a9727d286c2510d6b702dfd367e6aaf5c6b0f), [`a97003a`](https://github.com/mastra-ai/mastra/commit/a97003aa1cf2f4022a41912324a1e77263b326b8), [`ccc141e`](https://github.com/mastra-ai/mastra/commit/ccc141ed27da0abc3a3fc28e9e5128152e8e37f4), [`fe3b897`](https://github.com/mastra-ai/mastra/commit/fe3b897c2ccbcd2b10e81b099438c7337feddf89), [`00123ba`](https://github.com/mastra-ai/mastra/commit/00123ba96dc9e5cd0b110420ebdba56d8f237b25), [`29c4309`](https://github.com/mastra-ai/mastra/commit/29c4309f818b24304c041bcb4a8f19b5f13f6b62), [`16785ce`](https://github.com/mastra-ai/mastra/commit/16785ced928f6f22638f4488cf8a125d99211799), [`de8239b`](https://github.com/mastra-ai/mastra/commit/de8239bdcb1d8c0cfa06da21f1569912a66bbc8a), [`b5e6cd7`](https://github.com/mastra-ai/mastra/commit/b5e6cd77fc8c8e64e0494c1d06cee3d84e795d1e), [`3759cb0`](https://github.com/mastra-ai/mastra/commit/3759cb064935b5f74c65ac2f52a1145f7352899d), [`651e772`](https://github.com/mastra-ai/mastra/commit/651e772eb1475fb13e126d3fcc01751297a88214), [`b61b93f`](https://github.com/mastra-ai/mastra/commit/b61b93f9e058b11dd2eec169853175d31dbdd567), [`bae33d9`](https://github.com/mastra-ai/mastra/commit/bae33d91a63fbb64d1e80519e1fc1acaed1e9013), [`c0b731f`](https://github.com/mastra-ai/mastra/commit/c0b731fb27d712dc8582e846df5c0332a6a0c5ba), [`43ca8f2`](https://github.com/mastra-ai/mastra/commit/43ca8f2c7334851cc7b4d3d2f037d8784bfbdd5f), [`2ca67cc`](https://github.com/mastra-ai/mastra/commit/2ca67cc3bb1f6a617353fdcab197d9efebe60d6f), [`9e67002`](https://github.com/mastra-ai/mastra/commit/9e67002b52c9be19936c420a489dbee9c5fd6a78), [`35edc49`](https://github.com/mastra-ai/mastra/commit/35edc49ac0556db609189641d6341e76771b81fc)]:
|
|
10
|
+
- @mastra/core@1.0.0-beta.5
|
|
11
|
+
|
|
3
12
|
## 1.0.0-beta.1
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -327,6 +327,9 @@ The system automatically detects configuration changes and only rebuilds indexes
|
|
|
327
327
|
- `buildIndex({indexName, metric?, indexConfig?})`: Build or rebuild vector index
|
|
328
328
|
- `upsert({indexName, vectors, metadata?, ids?})`: Add or update vectors
|
|
329
329
|
- `query({indexName, queryVector, topK?, filter?, includeVector?, minScore?})`: Search for similar vectors
|
|
330
|
+
- `updateVector({ indexName, id?, filter?, update })`: Update a single vector by ID or metadata filter
|
|
331
|
+
- `deleteVector({ indexName, id })`: Delete a single vector by ID
|
|
332
|
+
- `deleteVectors({ indexName, ids?, filter? })`: Delete multiple vectors by IDs or metadata filter
|
|
330
333
|
- `listIndexes()`: List all vector-enabled tables
|
|
331
334
|
- `describeIndex(indexName)`: Get table statistics and index configuration
|
|
332
335
|
- `deleteIndex(indexName)`: Delete a table
|
package/dist/index.cjs
CHANGED
|
@@ -152,12 +152,20 @@ var createBasicOperator = (symbol) => {
|
|
|
152
152
|
};
|
|
153
153
|
};
|
|
154
154
|
var createNumericOperator = (symbol) => {
|
|
155
|
-
return (key, paramIndex) => {
|
|
155
|
+
return (key, paramIndex, value) => {
|
|
156
156
|
const jsonPathKey = parseJsonPathKey(key);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
const isNumeric = typeof value === "number" || typeof value === "string" && !isNaN(Number(value)) && value.trim() !== "";
|
|
158
|
+
if (isNumeric) {
|
|
159
|
+
return {
|
|
160
|
+
sql: `(metadata#>>'{${jsonPathKey}}')::numeric ${symbol} $${paramIndex}::numeric`,
|
|
161
|
+
needsValue: true
|
|
162
|
+
};
|
|
163
|
+
} else {
|
|
164
|
+
return {
|
|
165
|
+
sql: `metadata#>>'{${jsonPathKey}}' ${symbol} $${paramIndex}::text`,
|
|
166
|
+
needsValue: true
|
|
167
|
+
};
|
|
168
|
+
}
|
|
161
169
|
};
|
|
162
170
|
};
|
|
163
171
|
function buildElemMatchConditions(value, paramIndex) {
|
|
@@ -338,6 +346,83 @@ var parseJsonPathKey = (key) => {
|
|
|
338
346
|
function escapeLikePattern(str) {
|
|
339
347
|
return str.replace(/([%_\\])/g, "\\$1");
|
|
340
348
|
}
|
|
349
|
+
function buildDeleteFilterQuery(filter) {
|
|
350
|
+
const values = [];
|
|
351
|
+
function buildCondition(key, value, parentPath) {
|
|
352
|
+
if (["$and", "$or", "$not", "$nor"].includes(key)) {
|
|
353
|
+
return handleLogicalOperator(key, value);
|
|
354
|
+
}
|
|
355
|
+
if (!value || typeof value !== "object") {
|
|
356
|
+
values.push(value);
|
|
357
|
+
return `metadata#>>'{${parseJsonPathKey(key)}}' = $${values.length}`;
|
|
358
|
+
}
|
|
359
|
+
const [[operator, operatorValue] = []] = Object.entries(value);
|
|
360
|
+
if (operator === "$not") {
|
|
361
|
+
const entries = Object.entries(operatorValue);
|
|
362
|
+
const conditions2 = entries.map(([nestedOp, nestedValue]) => {
|
|
363
|
+
if (!FILTER_OPERATORS[nestedOp]) {
|
|
364
|
+
throw new Error(`Invalid operator in $not condition: ${nestedOp}`);
|
|
365
|
+
}
|
|
366
|
+
const operatorFn2 = FILTER_OPERATORS[nestedOp];
|
|
367
|
+
const operatorResult2 = operatorFn2(key, values.length + 1, nestedValue);
|
|
368
|
+
if (operatorResult2.needsValue) {
|
|
369
|
+
values.push(nestedValue);
|
|
370
|
+
}
|
|
371
|
+
return operatorResult2.sql;
|
|
372
|
+
}).join(" AND ");
|
|
373
|
+
return `NOT (${conditions2})`;
|
|
374
|
+
}
|
|
375
|
+
const operatorFn = FILTER_OPERATORS[operator];
|
|
376
|
+
const operatorResult = operatorFn(key, values.length + 1, operatorValue);
|
|
377
|
+
if (operatorResult.needsValue) {
|
|
378
|
+
const transformedValue = operatorResult.transformValue ? operatorResult.transformValue() : operatorValue;
|
|
379
|
+
if (Array.isArray(transformedValue) && operator === "$elemMatch") {
|
|
380
|
+
values.push(...transformedValue);
|
|
381
|
+
} else {
|
|
382
|
+
values.push(transformedValue);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return operatorResult.sql;
|
|
386
|
+
}
|
|
387
|
+
function handleLogicalOperator(key, value, parentPath) {
|
|
388
|
+
if (key === "$not") {
|
|
389
|
+
const entries = Object.entries(value);
|
|
390
|
+
const conditions3 = entries.map(([fieldKey, fieldValue]) => buildCondition(fieldKey, fieldValue)).join(" AND ");
|
|
391
|
+
return `NOT (${conditions3})`;
|
|
392
|
+
}
|
|
393
|
+
if (!value || value.length === 0) {
|
|
394
|
+
switch (key) {
|
|
395
|
+
case "$and":
|
|
396
|
+
case "$nor":
|
|
397
|
+
return "true";
|
|
398
|
+
// Empty $and/$nor match everything
|
|
399
|
+
case "$or":
|
|
400
|
+
return "false";
|
|
401
|
+
// Empty $or matches nothing
|
|
402
|
+
default:
|
|
403
|
+
return "true";
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const joinOperator = key === "$or" || key === "$nor" ? "OR" : "AND";
|
|
407
|
+
const conditions2 = value.map((f) => {
|
|
408
|
+
const entries = Object.entries(f || {});
|
|
409
|
+
if (entries.length === 0) return "";
|
|
410
|
+
const [firstKey, firstValue] = entries[0] || [];
|
|
411
|
+
if (["$and", "$or", "$not", "$nor"].includes(firstKey)) {
|
|
412
|
+
return buildCondition(firstKey, firstValue);
|
|
413
|
+
}
|
|
414
|
+
return entries.map(([k, v]) => buildCondition(k, v)).join(` ${joinOperator} `);
|
|
415
|
+
});
|
|
416
|
+
const joined = conditions2.join(` ${joinOperator} `);
|
|
417
|
+
const operatorFn = FILTER_OPERATORS[key];
|
|
418
|
+
return operatorFn(joined, 0, value).sql;
|
|
419
|
+
}
|
|
420
|
+
if (!filter) {
|
|
421
|
+
return { sql: "", values };
|
|
422
|
+
}
|
|
423
|
+
const conditions = Object.entries(filter).map(([key, value]) => buildCondition(key, value)).filter(Boolean).join(" AND ");
|
|
424
|
+
return { sql: conditions ? `WHERE ${conditions}` : "", values };
|
|
425
|
+
}
|
|
341
426
|
function buildFilterQuery(filter, minScore, topK) {
|
|
342
427
|
const values = [minScore, topK];
|
|
343
428
|
function buildCondition(key, value, parentPath) {
|
|
@@ -659,11 +744,31 @@ var PgVector = class extends vector.MastraVector {
|
|
|
659
744
|
client.release();
|
|
660
745
|
}
|
|
661
746
|
}
|
|
662
|
-
async upsert({
|
|
747
|
+
async upsert({
|
|
748
|
+
indexName,
|
|
749
|
+
vectors,
|
|
750
|
+
metadata,
|
|
751
|
+
ids,
|
|
752
|
+
deleteFilter
|
|
753
|
+
}) {
|
|
663
754
|
const { tableName } = this.getTableName(indexName);
|
|
664
755
|
const client = await this.pool.connect();
|
|
665
756
|
try {
|
|
666
757
|
await client.query("BEGIN");
|
|
758
|
+
if (deleteFilter) {
|
|
759
|
+
this.logger?.debug(`Deleting vectors matching filter before upsert`, { indexName, deleteFilter });
|
|
760
|
+
const translatedFilter = this.transformFilter(deleteFilter);
|
|
761
|
+
const { sql: filterQuery, values: filterValues } = buildDeleteFilterQuery(translatedFilter);
|
|
762
|
+
const whereClause = filterQuery.trim().replace(/^WHERE\s+/i, "");
|
|
763
|
+
if (whereClause) {
|
|
764
|
+
const deleteQuery = `DELETE FROM ${tableName} WHERE ${whereClause}`;
|
|
765
|
+
const result = await client.query(deleteQuery, filterValues);
|
|
766
|
+
this.logger?.debug(`Deleted ${result.rowCount || 0} vectors before upsert`, {
|
|
767
|
+
indexName,
|
|
768
|
+
deletedCount: result.rowCount || 0
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
}
|
|
667
772
|
const vectorIds = ids || vectors.map(() => crypto.randomUUID());
|
|
668
773
|
const vectorType = this.getVectorTypeName();
|
|
669
774
|
for (let i = 0; i < vectors.length; i++) {
|
|
@@ -679,6 +784,11 @@ var PgVector = class extends vector.MastraVector {
|
|
|
679
784
|
await client.query(query, [vectorIds[i], `[${vectors[i]?.join(",")}]`, JSON.stringify(metadata?.[i] || {})]);
|
|
680
785
|
}
|
|
681
786
|
await client.query("COMMIT");
|
|
787
|
+
this.logger?.debug(`Upserted ${vectors.length} vectors to ${indexName}`, {
|
|
788
|
+
indexName,
|
|
789
|
+
vectorCount: vectors.length,
|
|
790
|
+
hadDeleteFilter: !!deleteFilter
|
|
791
|
+
});
|
|
682
792
|
return vectorIds;
|
|
683
793
|
} catch (error$1) {
|
|
684
794
|
await client.query("ROLLBACK");
|
|
@@ -1236,17 +1346,36 @@ var PgVector = class extends vector.MastraVector {
|
|
|
1236
1346
|
* @returns A promise that resolves when the update is complete.
|
|
1237
1347
|
* @throws Will throw an error if no updates are provided or if the update operation fails.
|
|
1238
1348
|
*/
|
|
1239
|
-
async updateVector({ indexName, id, update }) {
|
|
1349
|
+
async updateVector({ indexName, id, filter, update }) {
|
|
1240
1350
|
let client;
|
|
1241
1351
|
try {
|
|
1242
1352
|
if (!update.vector && !update.metadata) {
|
|
1243
1353
|
throw new Error("No updates provided");
|
|
1244
1354
|
}
|
|
1355
|
+
if (!id && !filter) {
|
|
1356
|
+
throw new error.MastraError({
|
|
1357
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPDATE_MISSING_PARAMS",
|
|
1358
|
+
text: "Either id or filter must be provided",
|
|
1359
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1360
|
+
category: error.ErrorCategory.USER,
|
|
1361
|
+
details: { indexName }
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
if (id && filter) {
|
|
1365
|
+
throw new error.MastraError({
|
|
1366
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPDATE_CONFLICTING_PARAMS",
|
|
1367
|
+
text: "Cannot provide both id and filter - they are mutually exclusive",
|
|
1368
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1369
|
+
category: error.ErrorCategory.USER,
|
|
1370
|
+
details: { indexName }
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1245
1373
|
client = await this.pool.connect();
|
|
1246
|
-
|
|
1247
|
-
let values = [id];
|
|
1248
|
-
let valueIndex = 2;
|
|
1374
|
+
const { tableName } = this.getTableName(indexName);
|
|
1249
1375
|
const vectorType = this.getVectorTypeName();
|
|
1376
|
+
let updateParts = [];
|
|
1377
|
+
let values = [];
|
|
1378
|
+
let valueIndex = 1;
|
|
1250
1379
|
if (update.vector) {
|
|
1251
1380
|
updateParts.push(`embedding = $${valueIndex}::${vectorType}`);
|
|
1252
1381
|
values.push(`[${update.vector.join(",")}]`);
|
|
@@ -1255,18 +1384,60 @@ var PgVector = class extends vector.MastraVector {
|
|
|
1255
1384
|
if (update.metadata) {
|
|
1256
1385
|
updateParts.push(`metadata = $${valueIndex}::jsonb`);
|
|
1257
1386
|
values.push(JSON.stringify(update.metadata));
|
|
1387
|
+
valueIndex++;
|
|
1258
1388
|
}
|
|
1259
1389
|
if (updateParts.length === 0) {
|
|
1260
1390
|
return;
|
|
1261
1391
|
}
|
|
1262
|
-
|
|
1392
|
+
let whereClause;
|
|
1393
|
+
let whereValues;
|
|
1394
|
+
if (id) {
|
|
1395
|
+
whereClause = `vector_id = $${valueIndex}`;
|
|
1396
|
+
whereValues = [id];
|
|
1397
|
+
} else {
|
|
1398
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
1399
|
+
throw new error.MastraError({
|
|
1400
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPDATE_EMPTY_FILTER",
|
|
1401
|
+
text: "Cannot update with empty filter",
|
|
1402
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1403
|
+
category: error.ErrorCategory.USER,
|
|
1404
|
+
details: { indexName }
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
const translatedFilter = this.transformFilter(filter);
|
|
1408
|
+
const { sql: filterQuery, values: filterValues } = buildDeleteFilterQuery(translatedFilter);
|
|
1409
|
+
whereClause = filterQuery.trim().replace(/^WHERE\s+/i, "");
|
|
1410
|
+
if (!whereClause) {
|
|
1411
|
+
throw new error.MastraError({
|
|
1412
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPDATE_INVALID_FILTER",
|
|
1413
|
+
text: "Filter produced empty WHERE clause",
|
|
1414
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1415
|
+
category: error.ErrorCategory.USER,
|
|
1416
|
+
details: { indexName, filter: JSON.stringify(filter) }
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
whereClause = whereClause.replace(/\$(\d+)/g, (match, num) => {
|
|
1420
|
+
const newIndex = parseInt(num) + valueIndex - 1;
|
|
1421
|
+
return `$${newIndex}`;
|
|
1422
|
+
});
|
|
1423
|
+
whereValues = filterValues;
|
|
1424
|
+
}
|
|
1263
1425
|
const query = `
|
|
1264
1426
|
UPDATE ${tableName}
|
|
1265
1427
|
SET ${updateParts.join(", ")}
|
|
1266
|
-
WHERE
|
|
1428
|
+
WHERE ${whereClause}
|
|
1267
1429
|
`;
|
|
1268
|
-
await client.query(query, values);
|
|
1430
|
+
const result = await client.query(query, [...values, ...whereValues]);
|
|
1431
|
+
this.logger?.info(`Updated ${result.rowCount || 0} vectors in ${indexName}`, {
|
|
1432
|
+
indexName,
|
|
1433
|
+
id: id ? id : void 0,
|
|
1434
|
+
filter: filter ? filter : void 0,
|
|
1435
|
+
updatedCount: result.rowCount || 0
|
|
1436
|
+
});
|
|
1269
1437
|
} catch (error$1) {
|
|
1438
|
+
if (error$1 instanceof error.MastraError) {
|
|
1439
|
+
throw error$1;
|
|
1440
|
+
}
|
|
1270
1441
|
const mastraError = new error.MastraError(
|
|
1271
1442
|
{
|
|
1272
1443
|
id: "MASTRA_STORAGE_PG_VECTOR_UPDATE_VECTOR_FAILED",
|
|
@@ -1274,7 +1445,8 @@ var PgVector = class extends vector.MastraVector {
|
|
|
1274
1445
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1275
1446
|
details: {
|
|
1276
1447
|
indexName,
|
|
1277
|
-
id
|
|
1448
|
+
...id && { id },
|
|
1449
|
+
...filter && { filter: JSON.stringify(filter) }
|
|
1278
1450
|
}
|
|
1279
1451
|
},
|
|
1280
1452
|
error$1
|
|
@@ -1321,6 +1493,106 @@ var PgVector = class extends vector.MastraVector {
|
|
|
1321
1493
|
client?.release();
|
|
1322
1494
|
}
|
|
1323
1495
|
}
|
|
1496
|
+
/**
|
|
1497
|
+
* Delete vectors matching a metadata filter.
|
|
1498
|
+
* @param indexName - The name of the index containing the vectors.
|
|
1499
|
+
* @param filter - The filter to match vectors for deletion.
|
|
1500
|
+
* @returns A promise that resolves when the deletion is complete.
|
|
1501
|
+
* @throws Will throw an error if the deletion operation fails.
|
|
1502
|
+
*/
|
|
1503
|
+
async deleteVectors({ indexName, filter, ids }) {
|
|
1504
|
+
let client;
|
|
1505
|
+
try {
|
|
1506
|
+
client = await this.pool.connect();
|
|
1507
|
+
const { tableName } = this.getTableName(indexName);
|
|
1508
|
+
if (!filter && !ids) {
|
|
1509
|
+
throw new error.MastraError({
|
|
1510
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_MISSING_PARAMS",
|
|
1511
|
+
text: "Either filter or ids must be provided",
|
|
1512
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1513
|
+
category: error.ErrorCategory.USER,
|
|
1514
|
+
details: { indexName }
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
if (filter && ids) {
|
|
1518
|
+
throw new error.MastraError({
|
|
1519
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_CONFLICTING_PARAMS",
|
|
1520
|
+
text: "Cannot provide both filter and ids - they are mutually exclusive",
|
|
1521
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1522
|
+
category: error.ErrorCategory.USER,
|
|
1523
|
+
details: { indexName }
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
let query;
|
|
1527
|
+
let values;
|
|
1528
|
+
if (ids) {
|
|
1529
|
+
if (ids.length === 0) {
|
|
1530
|
+
throw new error.MastraError({
|
|
1531
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_EMPTY_IDS",
|
|
1532
|
+
text: "Cannot delete with empty ids array",
|
|
1533
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1534
|
+
category: error.ErrorCategory.USER,
|
|
1535
|
+
details: { indexName }
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
const placeholders = ids.map((_, i) => `$${i + 1}`).join(", ");
|
|
1539
|
+
query = `DELETE FROM ${tableName} WHERE vector_id IN (${placeholders})`;
|
|
1540
|
+
values = ids;
|
|
1541
|
+
} else {
|
|
1542
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
1543
|
+
throw new error.MastraError({
|
|
1544
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_EMPTY_FILTER",
|
|
1545
|
+
text: "Cannot delete with empty filter. Use deleteIndex to delete all vectors.",
|
|
1546
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1547
|
+
category: error.ErrorCategory.USER,
|
|
1548
|
+
details: { indexName }
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
const translatedFilter = this.transformFilter(filter);
|
|
1552
|
+
const { sql: filterQuery, values: filterValues } = buildDeleteFilterQuery(translatedFilter);
|
|
1553
|
+
const whereClause = filterQuery.trim().replace(/^WHERE\s+/i, "");
|
|
1554
|
+
if (!whereClause) {
|
|
1555
|
+
throw new error.MastraError({
|
|
1556
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_INVALID_FILTER",
|
|
1557
|
+
text: "Filter produced empty WHERE clause",
|
|
1558
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1559
|
+
category: error.ErrorCategory.USER,
|
|
1560
|
+
details: { indexName, filter: JSON.stringify(filter) }
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
query = `DELETE FROM ${tableName} WHERE ${whereClause}`;
|
|
1564
|
+
values = filterValues;
|
|
1565
|
+
}
|
|
1566
|
+
const result = await client.query(query, values);
|
|
1567
|
+
this.logger?.info(`Deleted ${result.rowCount || 0} vectors from ${indexName}`, {
|
|
1568
|
+
indexName,
|
|
1569
|
+
filter: filter ? filter : void 0,
|
|
1570
|
+
ids: ids ? ids : void 0,
|
|
1571
|
+
deletedCount: result.rowCount || 0
|
|
1572
|
+
});
|
|
1573
|
+
} catch (error$1) {
|
|
1574
|
+
if (error$1 instanceof error.MastraError) {
|
|
1575
|
+
throw error$1;
|
|
1576
|
+
}
|
|
1577
|
+
const mastraError = new error.MastraError(
|
|
1578
|
+
{
|
|
1579
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_VECTORS_FAILED",
|
|
1580
|
+
domain: error.ErrorDomain.MASTRA_VECTOR,
|
|
1581
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1582
|
+
details: {
|
|
1583
|
+
indexName,
|
|
1584
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
1585
|
+
...ids && { idsCount: ids.length }
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
error$1
|
|
1589
|
+
);
|
|
1590
|
+
this.logger?.trackException(mastraError);
|
|
1591
|
+
throw mastraError;
|
|
1592
|
+
} finally {
|
|
1593
|
+
client?.release();
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1324
1596
|
};
|
|
1325
1597
|
function getSchemaName(schema) {
|
|
1326
1598
|
return schema ? `"${utils.parseSqlIdentifier(schema, "schema name")}"` : void 0;
|