@mastra/couchbase 0.0.0-vector-query-sources-20250516172905 → 0.0.0-vector-query-tool-provider-options-20250828222356
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 +347 -2
- package/LICENSE.md +11 -42
- package/README.md +11 -1
- package/dist/index.cjs +286 -168
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +284 -166
- package/dist/index.js.map +1 -0
- package/dist/vector/index.d.ts +61 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/package.json +20 -16
- package/src/vector/index.ts +295 -214
- package/src/vector/index.unit.test.ts +1 -1
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +17 -0
- package/dist/_tsup-dts-rollup.d.cts +0 -86
- package/dist/_tsup-dts-rollup.d.ts +0 -86
- package/dist/index.d.cts +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/couchbase",
|
|
3
|
-
"version": "0.0.0-vector-query-
|
|
3
|
+
"version": "0.0.0-vector-query-tool-provider-options-20250828222356",
|
|
4
4
|
"description": "Couchbase vector store provider for Mastra",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,31 +12,35 @@
|
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"require": {
|
|
15
|
-
"types": "./dist/index.d.
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
16
|
"default": "./dist/index.cjs"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"./package.json": "./package.json"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"couchbase": "^4.
|
|
23
|
-
"@mastra/core": "0.0.0-vector-query-sources-20250516172905"
|
|
22
|
+
"couchbase": "^4.5.0"
|
|
24
23
|
},
|
|
25
24
|
"devDependencies": {
|
|
26
|
-
"@microsoft/api-extractor": "^7.52.
|
|
27
|
-
"@types/node": "^20.
|
|
28
|
-
"@vitest/coverage-v8": "3.
|
|
29
|
-
"@vitest/ui": "3.
|
|
30
|
-
"axios": "^1.
|
|
31
|
-
"eslint": "^9.
|
|
32
|
-
"tsup": "^8.
|
|
33
|
-
"typescript": "^5.8.
|
|
34
|
-
"vitest": "^3.
|
|
35
|
-
"@
|
|
25
|
+
"@microsoft/api-extractor": "^7.52.8",
|
|
26
|
+
"@types/node": "^20.19.0",
|
|
27
|
+
"@vitest/coverage-v8": "3.2.3",
|
|
28
|
+
"@vitest/ui": "3.2.3",
|
|
29
|
+
"axios": "^1.11.0",
|
|
30
|
+
"eslint": "^9.30.1",
|
|
31
|
+
"tsup": "^8.5.0",
|
|
32
|
+
"typescript": "^5.8.3",
|
|
33
|
+
"vitest": "^3.2.4",
|
|
34
|
+
"@mastra/core": "0.0.0-vector-query-tool-provider-options-20250828222356",
|
|
35
|
+
"@internal/types-builder": "0.0.0-vector-query-tool-provider-options-20250828222356",
|
|
36
|
+
"@internal/lint": "0.0.0-vector-query-tool-provider-options-20250828222356"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@mastra/core": "0.0.0-vector-query-tool-provider-options-20250828222356"
|
|
36
40
|
},
|
|
37
41
|
"scripts": {
|
|
38
|
-
"build": "tsup
|
|
39
|
-
"build:watch": "
|
|
42
|
+
"build": "tsup --silent --config tsup.config.ts",
|
|
43
|
+
"build:watch": "tsup --watch --silent --config tsup.config.ts",
|
|
40
44
|
"lint": "eslint .",
|
|
41
45
|
"coverage": "vitest run --coverage",
|
|
42
46
|
"pretest": "node scripts/start-docker.js",
|
package/src/vector/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
|
|
1
2
|
import { MastraVector } from '@mastra/core/vector';
|
|
2
3
|
import type {
|
|
3
4
|
QueryResult,
|
|
@@ -6,7 +7,6 @@ import type {
|
|
|
6
7
|
UpsertVectorParams,
|
|
7
8
|
QueryVectorParams,
|
|
8
9
|
DescribeIndexParams,
|
|
9
|
-
ParamsToArgs,
|
|
10
10
|
DeleteIndexParams,
|
|
11
11
|
DeleteVectorParams,
|
|
12
12
|
UpdateVectorParams,
|
|
@@ -42,85 +42,50 @@ export class CouchbaseVector extends MastraVector {
|
|
|
42
42
|
private scope: Scope;
|
|
43
43
|
private vector_dimension: number;
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
* @deprecated Passing parameters as positional arguments is deprecated.
|
|
47
|
-
* Use the object parameter instead. This signature will be removed on May 20th, 2025.
|
|
48
|
-
*/
|
|
49
|
-
constructor(
|
|
50
|
-
connectionString: string,
|
|
51
|
-
username: string,
|
|
52
|
-
password: string,
|
|
53
|
-
bucketName: string,
|
|
54
|
-
scopeName: string,
|
|
55
|
-
collectionName: string,
|
|
56
|
-
);
|
|
57
|
-
constructor(params: CouchbaseVectorParams);
|
|
58
|
-
constructor(
|
|
59
|
-
paramsOrConnectionString: CouchbaseVectorParams | string,
|
|
60
|
-
username?: string,
|
|
61
|
-
password?: string,
|
|
62
|
-
bucketName?: string,
|
|
63
|
-
scopeName?: string,
|
|
64
|
-
collectionName?: string,
|
|
65
|
-
) {
|
|
66
|
-
let connectionString_: string,
|
|
67
|
-
username_: string,
|
|
68
|
-
password_: string,
|
|
69
|
-
bucketName_: string,
|
|
70
|
-
scopeName_: string,
|
|
71
|
-
collectionName_: string;
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
typeof paramsOrConnectionString === 'object' &&
|
|
75
|
-
paramsOrConnectionString !== null &&
|
|
76
|
-
'connectionString' in paramsOrConnectionString
|
|
77
|
-
) {
|
|
78
|
-
// Object params (preferred)
|
|
79
|
-
connectionString_ = paramsOrConnectionString.connectionString as string;
|
|
80
|
-
username_ = paramsOrConnectionString.username;
|
|
81
|
-
password_ = paramsOrConnectionString.password;
|
|
82
|
-
bucketName_ = paramsOrConnectionString.bucketName;
|
|
83
|
-
scopeName_ = paramsOrConnectionString.scopeName;
|
|
84
|
-
collectionName_ = paramsOrConnectionString.collectionName;
|
|
85
|
-
} else {
|
|
86
|
-
// Positional args (deprecated)
|
|
87
|
-
if (arguments.length > 1) {
|
|
88
|
-
console.warn(
|
|
89
|
-
'Deprecation Warning: CouchbaseVector constructor positional arguments are deprecated. Please use a single object parameter instead. This signature will be removed on May 20th, 2025.',
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
connectionString_ = paramsOrConnectionString as string;
|
|
93
|
-
username_ = username!;
|
|
94
|
-
password_ = password!;
|
|
95
|
-
bucketName_ = bucketName!;
|
|
96
|
-
scopeName_ = scopeName!;
|
|
97
|
-
collectionName_ = collectionName!;
|
|
98
|
-
}
|
|
99
|
-
|
|
45
|
+
constructor({ connectionString, username, password, bucketName, scopeName, collectionName }: CouchbaseVectorParams) {
|
|
100
46
|
super();
|
|
101
47
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
48
|
+
try {
|
|
49
|
+
const baseClusterPromise = connect(connectionString, {
|
|
50
|
+
username,
|
|
51
|
+
password,
|
|
52
|
+
configProfile: 'wanDevelopment',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const telemetry = this.__getTelemetry();
|
|
56
|
+
this.clusterPromise =
|
|
57
|
+
telemetry?.traceClass(baseClusterPromise, {
|
|
58
|
+
spanNamePrefix: 'couchbase-vector',
|
|
59
|
+
attributes: {
|
|
60
|
+
'vector.type': 'couchbase',
|
|
61
|
+
},
|
|
62
|
+
}) ?? baseClusterPromise;
|
|
63
|
+
this.cluster = null as unknown as Cluster;
|
|
64
|
+
this.bucketName = bucketName;
|
|
65
|
+
this.collectionName = collectionName;
|
|
66
|
+
this.scopeName = scopeName;
|
|
67
|
+
this.collection = null as unknown as Collection;
|
|
68
|
+
this.bucket = null as unknown as Bucket;
|
|
69
|
+
this.scope = null as unknown as Scope;
|
|
70
|
+
this.vector_dimension = null as unknown as number;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
throw new MastraError(
|
|
73
|
+
{
|
|
74
|
+
id: 'COUCHBASE_VECTOR_INITIALIZE_FAILED',
|
|
75
|
+
domain: ErrorDomain.STORAGE,
|
|
76
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
77
|
+
details: {
|
|
78
|
+
connectionString,
|
|
79
|
+
username,
|
|
80
|
+
password,
|
|
81
|
+
bucketName,
|
|
82
|
+
scopeName,
|
|
83
|
+
collectionName,
|
|
84
|
+
},
|
|
114
85
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.collectionName = collectionName_;
|
|
119
|
-
this.scopeName = scopeName_;
|
|
120
|
-
this.collection = null as unknown as Collection;
|
|
121
|
-
this.bucket = null as unknown as Bucket;
|
|
122
|
-
this.scope = null as unknown as Scope;
|
|
123
|
-
this.vector_dimension = null as unknown as number;
|
|
86
|
+
error,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
124
89
|
}
|
|
125
90
|
|
|
126
91
|
async getCollection() {
|
|
@@ -137,15 +102,14 @@ export class CouchbaseVector extends MastraVector {
|
|
|
137
102
|
return this.collection;
|
|
138
103
|
}
|
|
139
104
|
|
|
140
|
-
async createIndex(
|
|
141
|
-
|
|
142
|
-
|
|
105
|
+
async createIndex({ indexName, dimension, metric = 'dotproduct' as MastraMetric }: CreateIndexParams): Promise<void> {
|
|
106
|
+
try {
|
|
107
|
+
await this.getCollection();
|
|
143
108
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
109
|
+
if (!Number.isInteger(dimension) || dimension <= 0) {
|
|
110
|
+
throw new Error('Dimension must be a positive integer');
|
|
111
|
+
}
|
|
147
112
|
|
|
148
|
-
try {
|
|
149
113
|
await this.scope.searchIndexes().upsertIndex({
|
|
150
114
|
name: indexName,
|
|
151
115
|
sourceName: this.bucketName,
|
|
@@ -229,132 +193,206 @@ export class CouchbaseVector extends MastraVector {
|
|
|
229
193
|
await this.validateExistingIndex(indexName, dimension, metric);
|
|
230
194
|
return;
|
|
231
195
|
}
|
|
232
|
-
throw
|
|
196
|
+
throw new MastraError(
|
|
197
|
+
{
|
|
198
|
+
id: 'COUCHBASE_VECTOR_CREATE_INDEX_FAILED',
|
|
199
|
+
domain: ErrorDomain.STORAGE,
|
|
200
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
201
|
+
details: {
|
|
202
|
+
indexName,
|
|
203
|
+
dimension,
|
|
204
|
+
metric,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
error,
|
|
208
|
+
);
|
|
233
209
|
}
|
|
234
210
|
}
|
|
235
211
|
|
|
236
|
-
async upsert(
|
|
237
|
-
|
|
238
|
-
|
|
212
|
+
async upsert({ vectors, metadata, ids }: UpsertVectorParams): Promise<string[]> {
|
|
213
|
+
try {
|
|
214
|
+
await this.getCollection();
|
|
239
215
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
216
|
+
if (!vectors || vectors.length === 0) {
|
|
217
|
+
throw new Error('No vectors provided');
|
|
218
|
+
}
|
|
219
|
+
if (this.vector_dimension) {
|
|
220
|
+
for (const vector of vectors) {
|
|
221
|
+
if (!vector || this.vector_dimension !== vector.length) {
|
|
222
|
+
throw new Error('Vector dimension mismatch');
|
|
223
|
+
}
|
|
247
224
|
}
|
|
248
225
|
}
|
|
249
|
-
}
|
|
250
226
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
227
|
+
const pointIds = ids || vectors.map(() => crypto.randomUUID());
|
|
228
|
+
const records = vectors.map((vector, i) => {
|
|
229
|
+
const metadataObj = metadata?.[i] || {};
|
|
230
|
+
const record: Record<string, any> = {
|
|
231
|
+
embedding: vector,
|
|
232
|
+
metadata: metadataObj,
|
|
233
|
+
};
|
|
234
|
+
// If metadata has a text field, save it as content
|
|
235
|
+
if (metadataObj.text) {
|
|
236
|
+
record.content = metadataObj.text;
|
|
237
|
+
}
|
|
238
|
+
return record;
|
|
239
|
+
});
|
|
264
240
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
241
|
+
const allPromises = [];
|
|
242
|
+
for (let i = 0; i < records.length; i++) {
|
|
243
|
+
allPromises.push(this.collection.upsert(pointIds[i]!, records[i]));
|
|
244
|
+
}
|
|
245
|
+
await Promise.all(allPromises);
|
|
246
|
+
|
|
247
|
+
return pointIds;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
throw new MastraError(
|
|
250
|
+
{
|
|
251
|
+
id: 'COUCHBASE_VECTOR_UPSERT_FAILED',
|
|
252
|
+
domain: ErrorDomain.STORAGE,
|
|
253
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
254
|
+
},
|
|
255
|
+
error,
|
|
256
|
+
);
|
|
268
257
|
}
|
|
269
|
-
await Promise.all(allPromises);
|
|
270
|
-
|
|
271
|
-
return pointIds;
|
|
272
258
|
}
|
|
273
259
|
|
|
274
|
-
async query(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
await this.getCollection();
|
|
260
|
+
async query({ indexName, queryVector, topK = 10, includeVector = false }: QueryVectorParams): Promise<QueryResult[]> {
|
|
261
|
+
try {
|
|
262
|
+
await this.getCollection();
|
|
278
263
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
264
|
+
const index_stats = await this.describeIndex({ indexName });
|
|
265
|
+
if (queryVector.length !== index_stats.dimension) {
|
|
266
|
+
throw new Error(
|
|
267
|
+
`Query vector dimension mismatch. Expected ${index_stats.dimension}, got ${queryVector.length}`,
|
|
268
|
+
);
|
|
269
|
+
}
|
|
283
270
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
271
|
+
let request = SearchRequest.create(
|
|
272
|
+
VectorSearch.fromVectorQuery(VectorQuery.create('embedding', queryVector).numCandidates(topK)),
|
|
273
|
+
);
|
|
274
|
+
const results = await this.scope.search(indexName, request, {
|
|
275
|
+
fields: ['*'],
|
|
276
|
+
});
|
|
290
277
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
278
|
+
if (includeVector) {
|
|
279
|
+
throw new Error('Including vectors in search results is not yet supported by the Couchbase vector store');
|
|
280
|
+
}
|
|
281
|
+
const output = [];
|
|
282
|
+
for (const match of results.rows) {
|
|
283
|
+
const cleanedMetadata: Record<string, any> = {};
|
|
284
|
+
const fields = (match.fields as Record<string, any>) || {}; // Ensure fields is an object
|
|
285
|
+
for (const key in fields) {
|
|
286
|
+
if (Object.prototype.hasOwnProperty.call(fields, key)) {
|
|
287
|
+
const newKey = key.startsWith('metadata.') ? key.substring('metadata.'.length) : key;
|
|
288
|
+
cleanedMetadata[newKey] = fields[key];
|
|
289
|
+
}
|
|
302
290
|
}
|
|
291
|
+
output.push({
|
|
292
|
+
id: match.id as string,
|
|
293
|
+
score: (match.score as number) || 0,
|
|
294
|
+
metadata: cleanedMetadata, // Use the cleaned metadata object
|
|
295
|
+
});
|
|
303
296
|
}
|
|
304
|
-
output
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
297
|
+
return output;
|
|
298
|
+
} catch (error) {
|
|
299
|
+
throw new MastraError(
|
|
300
|
+
{
|
|
301
|
+
id: 'COUCHBASE_VECTOR_QUERY_FAILED',
|
|
302
|
+
domain: ErrorDomain.STORAGE,
|
|
303
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
304
|
+
details: {
|
|
305
|
+
indexName,
|
|
306
|
+
topK,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
error,
|
|
310
|
+
);
|
|
309
311
|
}
|
|
310
|
-
return output;
|
|
311
312
|
}
|
|
312
313
|
|
|
313
314
|
async listIndexes(): Promise<string[]> {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
try {
|
|
316
|
+
await this.getCollection();
|
|
317
|
+
const indexes = await this.scope.searchIndexes().getAllIndexes();
|
|
318
|
+
return indexes?.map(index => index.name) || [];
|
|
319
|
+
} catch (error) {
|
|
320
|
+
throw new MastraError(
|
|
321
|
+
{
|
|
322
|
+
id: 'COUCHBASE_VECTOR_LIST_INDEXES_FAILED',
|
|
323
|
+
domain: ErrorDomain.STORAGE,
|
|
324
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
325
|
+
},
|
|
326
|
+
error,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
317
329
|
}
|
|
318
330
|
|
|
319
331
|
/**
|
|
320
332
|
* Retrieves statistics about a vector index.
|
|
321
333
|
*
|
|
322
|
-
* @param
|
|
323
|
-
* @param params.indexName - The name of the index to describe
|
|
334
|
+
* @param {string} indexName - The name of the index to describe
|
|
324
335
|
* @returns A promise that resolves to the index statistics including dimension, count and metric
|
|
325
336
|
*/
|
|
326
|
-
async describeIndex(
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
337
|
+
async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {
|
|
338
|
+
try {
|
|
339
|
+
await this.getCollection();
|
|
340
|
+
if (!(await this.listIndexes()).includes(indexName)) {
|
|
341
|
+
throw new Error(`Index ${indexName} does not exist`);
|
|
342
|
+
}
|
|
343
|
+
const index = await this.scope.searchIndexes().getIndex(indexName);
|
|
344
|
+
const dimensions =
|
|
345
|
+
index.params.mapping?.types?.[`${this.scopeName}.${this.collectionName}`]?.properties?.embedding?.fields?.[0]
|
|
346
|
+
?.dims;
|
|
347
|
+
const count = -1; // Not added support yet for adding a count of documents covered by an index
|
|
348
|
+
const metric = index.params.mapping?.types?.[`${this.scopeName}.${this.collectionName}`]?.properties?.embedding
|
|
349
|
+
?.fields?.[0]?.similarity as CouchbaseMetric;
|
|
350
|
+
return {
|
|
351
|
+
dimension: dimensions,
|
|
352
|
+
count: count,
|
|
353
|
+
metric: Object.keys(DISTANCE_MAPPING).find(
|
|
354
|
+
key => DISTANCE_MAPPING[key as MastraMetric] === metric,
|
|
355
|
+
) as MastraMetric,
|
|
356
|
+
};
|
|
357
|
+
} catch (error) {
|
|
358
|
+
throw new MastraError(
|
|
359
|
+
{
|
|
360
|
+
id: 'COUCHBASE_VECTOR_DESCRIBE_INDEX_FAILED',
|
|
361
|
+
domain: ErrorDomain.STORAGE,
|
|
362
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
363
|
+
details: {
|
|
364
|
+
indexName,
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
error,
|
|
368
|
+
);
|
|
332
369
|
}
|
|
333
|
-
const index = await this.scope.searchIndexes().getIndex(indexName);
|
|
334
|
-
const dimensions =
|
|
335
|
-
index.params.mapping?.types?.[`${this.scopeName}.${this.collectionName}`]?.properties?.embedding?.fields?.[0]
|
|
336
|
-
?.dims;
|
|
337
|
-
const count = -1; // Not added support yet for adding a count of documents covered by an index
|
|
338
|
-
const metric = index.params.mapping?.types?.[`${this.scopeName}.${this.collectionName}`]?.properties?.embedding
|
|
339
|
-
?.fields?.[0]?.similarity as CouchbaseMetric;
|
|
340
|
-
return {
|
|
341
|
-
dimension: dimensions,
|
|
342
|
-
count: count,
|
|
343
|
-
metric: Object.keys(DISTANCE_MAPPING).find(
|
|
344
|
-
key => DISTANCE_MAPPING[key as MastraMetric] === metric,
|
|
345
|
-
) as MastraMetric,
|
|
346
|
-
};
|
|
347
370
|
}
|
|
348
371
|
|
|
349
|
-
async deleteIndex(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
372
|
+
async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {
|
|
373
|
+
try {
|
|
374
|
+
await this.getCollection();
|
|
375
|
+
if (!(await this.listIndexes()).includes(indexName)) {
|
|
376
|
+
throw new Error(`Index ${indexName} does not exist`);
|
|
377
|
+
}
|
|
378
|
+
await this.scope.searchIndexes().dropIndex(indexName);
|
|
379
|
+
this.vector_dimension = null as unknown as number;
|
|
380
|
+
} catch (error) {
|
|
381
|
+
if (error instanceof MastraError) {
|
|
382
|
+
throw error;
|
|
383
|
+
}
|
|
384
|
+
throw new MastraError(
|
|
385
|
+
{
|
|
386
|
+
id: 'COUCHBASE_VECTOR_DELETE_INDEX_FAILED',
|
|
387
|
+
domain: ErrorDomain.STORAGE,
|
|
388
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
389
|
+
details: {
|
|
390
|
+
indexName,
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
error,
|
|
394
|
+
);
|
|
355
395
|
}
|
|
356
|
-
await this.scope.searchIndexes().dropIndex(indexName);
|
|
357
|
-
this.vector_dimension = null as unknown as number;
|
|
358
396
|
}
|
|
359
397
|
|
|
360
398
|
/**
|
|
@@ -367,32 +405,46 @@ export class CouchbaseVector extends MastraVector {
|
|
|
367
405
|
* @returns A promise that resolves when the update is complete.
|
|
368
406
|
* @throws Will throw an error if no updates are provided or if the update operation fails.
|
|
369
407
|
*/
|
|
370
|
-
async updateVector(
|
|
371
|
-
const params = this.normalizeArgs<UpdateVectorParams>('updateVector', args);
|
|
372
|
-
const { id, update } = params;
|
|
373
|
-
if (!update.vector && !update.metadata) {
|
|
374
|
-
throw new Error('No updates provided');
|
|
375
|
-
}
|
|
376
|
-
if (update.vector && this.vector_dimension && update.vector.length !== this.vector_dimension) {
|
|
377
|
-
throw new Error('Vector dimension mismatch');
|
|
378
|
-
}
|
|
379
|
-
const collection = await this.getCollection();
|
|
380
|
-
|
|
381
|
-
// Check if document exists
|
|
408
|
+
async updateVector({ id, update }: UpdateVectorParams): Promise<void> {
|
|
382
409
|
try {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
410
|
+
if (!update.vector && !update.metadata) {
|
|
411
|
+
throw new Error('No updates provided');
|
|
412
|
+
}
|
|
413
|
+
if (update.vector && this.vector_dimension && update.vector.length !== this.vector_dimension) {
|
|
414
|
+
throw new Error('Vector dimension mismatch');
|
|
415
|
+
}
|
|
416
|
+
const collection = await this.getCollection();
|
|
417
|
+
|
|
418
|
+
// Check if document exists
|
|
419
|
+
try {
|
|
420
|
+
await collection.get(id);
|
|
421
|
+
} catch (err: any) {
|
|
422
|
+
if (err.code === 13 || err.message?.includes('document not found')) {
|
|
423
|
+
throw new Error(`Vector with id ${id} does not exist`);
|
|
424
|
+
}
|
|
425
|
+
throw err;
|
|
387
426
|
}
|
|
388
|
-
throw err;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const specs: MutateInSpec[] = [];
|
|
392
|
-
if (update.vector) specs.push(MutateInSpec.replace('embedding', update.vector));
|
|
393
|
-
if (update.metadata) specs.push(MutateInSpec.replace('metadata', update.metadata));
|
|
394
427
|
|
|
395
|
-
|
|
428
|
+
const specs: MutateInSpec[] = [];
|
|
429
|
+
if (update.vector) specs.push(MutateInSpec.replace('embedding', update.vector));
|
|
430
|
+
if (update.metadata) specs.push(MutateInSpec.replace('metadata', update.metadata));
|
|
431
|
+
|
|
432
|
+
await collection.mutateIn(id, specs);
|
|
433
|
+
} catch (error) {
|
|
434
|
+
throw new MastraError(
|
|
435
|
+
{
|
|
436
|
+
id: 'COUCHBASE_VECTOR_UPDATE_FAILED',
|
|
437
|
+
domain: ErrorDomain.STORAGE,
|
|
438
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
439
|
+
details: {
|
|
440
|
+
id,
|
|
441
|
+
hasVectorUpdate: !!update.vector,
|
|
442
|
+
hasMetadataUpdate: !!update.metadata,
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
error,
|
|
446
|
+
);
|
|
447
|
+
}
|
|
396
448
|
}
|
|
397
449
|
|
|
398
450
|
/**
|
|
@@ -402,22 +454,51 @@ export class CouchbaseVector extends MastraVector {
|
|
|
402
454
|
* @returns A promise that resolves when the deletion is complete.
|
|
403
455
|
* @throws Will throw an error if the deletion operation fails.
|
|
404
456
|
*/
|
|
405
|
-
async deleteVector(
|
|
406
|
-
|
|
457
|
+
async deleteVector({ id }: DeleteVectorParams): Promise<void> {
|
|
458
|
+
try {
|
|
459
|
+
const collection = await this.getCollection();
|
|
460
|
+
|
|
461
|
+
// Check if document exists
|
|
462
|
+
try {
|
|
463
|
+
await collection.get(id);
|
|
464
|
+
} catch (err: any) {
|
|
465
|
+
if (err.code === 13 || err.message?.includes('document not found')) {
|
|
466
|
+
throw new Error(`Vector with id ${id} does not exist`);
|
|
467
|
+
}
|
|
468
|
+
throw err;
|
|
469
|
+
}
|
|
407
470
|
|
|
408
|
-
|
|
409
|
-
|
|
471
|
+
await collection.remove(id);
|
|
472
|
+
} catch (error) {
|
|
473
|
+
throw new MastraError(
|
|
474
|
+
{
|
|
475
|
+
id: 'COUCHBASE_VECTOR_DELETE_FAILED',
|
|
476
|
+
domain: ErrorDomain.STORAGE,
|
|
477
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
478
|
+
details: {
|
|
479
|
+
id,
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
error,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
410
486
|
|
|
411
|
-
|
|
487
|
+
async disconnect() {
|
|
412
488
|
try {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
if (err.code === 13 || err.message?.includes('document not found')) {
|
|
416
|
-
throw new Error(`Vector with id ${id} does not exist`);
|
|
489
|
+
if (!this.cluster) {
|
|
490
|
+
return;
|
|
417
491
|
}
|
|
418
|
-
|
|
492
|
+
await this.cluster.close();
|
|
493
|
+
} catch (error) {
|
|
494
|
+
throw new MastraError(
|
|
495
|
+
{
|
|
496
|
+
id: 'COUCHBASE_VECTOR_DISCONNECT_FAILED',
|
|
497
|
+
domain: ErrorDomain.STORAGE,
|
|
498
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
499
|
+
},
|
|
500
|
+
error,
|
|
501
|
+
);
|
|
419
502
|
}
|
|
420
|
-
|
|
421
|
-
await collection.remove(id);
|
|
422
503
|
}
|
|
423
504
|
}
|
|
@@ -323,7 +323,7 @@ describe('Unit Testing CouchbaseVector', () => {
|
|
|
323
323
|
expect(mockGetIndexFn).toHaveResolved();
|
|
324
324
|
|
|
325
325
|
expect(stats.dimension).toBe(dimension);
|
|
326
|
-
expect(stats.metric).toBe('euclidean'); //
|
|
326
|
+
expect(stats.metric).toBe('euclidean'); // similarity(=="l2_norm") is mapped to euclidean in couchbase
|
|
327
327
|
expect(typeof stats.count).toBe('number');
|
|
328
328
|
}, 50000);
|
|
329
329
|
|