@mastra/chroma 0.1.6-alpha.1 → 0.1.6-alpha.3

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.
@@ -1,5 +1,5 @@
1
1
  import type { QueryResult, IndexStats } from '@mastra/core/vector';
2
- import { describe, expect, beforeEach, afterEach, it, beforeAll, afterAll } from 'vitest';
2
+ import { describe, expect, beforeEach, afterEach, it, beforeAll, afterAll, vi } from 'vitest';
3
3
 
4
4
  import { ChromaVector } from './';
5
5
 
@@ -20,7 +20,7 @@ describe('ChromaVector Integration Tests', () => {
20
20
  } catch {
21
21
  // Ignore errors if index doesn't exist
22
22
  }
23
- await vectorDB.createIndex(testIndexName, dimension);
23
+ await vectorDB.createIndex({ indexName: testIndexName, dimension });
24
24
  }, 5000);
25
25
 
26
26
  afterEach(async () => {
@@ -56,7 +56,7 @@ describe('ChromaVector Integration Tests', () => {
56
56
 
57
57
  for (const metric of metricsToTest) {
58
58
  const testIndex = `test-index-${metric}`;
59
- await vectorDB.createIndex(testIndex, dimension, metric);
59
+ await vectorDB.createIndex({ indexName: testIndex, dimension, metric });
60
60
 
61
61
  const stats = await vectorDB.describeIndex(testIndex);
62
62
  expect(stats.metric).toBe(metric);
@@ -76,7 +76,7 @@ describe('ChromaVector Integration Tests', () => {
76
76
  const testIds = ['vec1', 'vec2', 'vec3'];
77
77
 
78
78
  it('should upsert vectors with generated ids', async () => {
79
- const ids = await vectorDB.upsert(testIndexName, testVectors);
79
+ const ids = await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors });
80
80
  expect(ids).toHaveLength(testVectors.length);
81
81
  ids.forEach(id => expect(typeof id).toBe('string'));
82
82
 
@@ -85,14 +85,14 @@ describe('ChromaVector Integration Tests', () => {
85
85
  });
86
86
 
87
87
  it('should upsert vectors with provided ids and metadata', async () => {
88
- await vectorDB.upsert(testIndexName, testVectors, testMetadata, testIds);
88
+ await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors, metadata: testMetadata, ids: testIds });
89
89
 
90
90
  const stats = await vectorDB.describeIndex(testIndexName);
91
91
  expect(stats.count).toBe(testVectors.length);
92
92
 
93
93
  // Query each vector to verify metadata
94
94
  for (let i = 0; i < testVectors.length; i++) {
95
- const results = await vectorDB.query(testIndexName, testVectors?.[i]!, 1);
95
+ const results = await vectorDB.query({ indexName: testIndexName, queryVector: testVectors?.[i]!, topK: 1 });
96
96
  expect(results?.[0]?.id).toBe(testIds[i]);
97
97
  expect(results?.[0]?.metadata).toEqual(testMetadata[i]);
98
98
  }
@@ -100,15 +100,20 @@ describe('ChromaVector Integration Tests', () => {
100
100
 
101
101
  it('should update existing vectors', async () => {
102
102
  // Initial upsert
103
- await vectorDB.upsert(testIndexName, testVectors, testMetadata, testIds);
103
+ await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors, metadata: testMetadata, ids: testIds });
104
104
 
105
105
  // Update first vector
106
106
  const updatedVector = [[0.5, 0.5, 0.0]];
107
107
  const updatedMetadata = [{ label: 'updated-x-axis' }];
108
- await vectorDB.upsert(testIndexName, updatedVector, updatedMetadata, [testIds?.[0]!]);
108
+ await vectorDB.upsert({
109
+ indexName: testIndexName,
110
+ vectors: updatedVector,
111
+ metadata: updatedMetadata,
112
+ ids: [testIds?.[0]!],
113
+ });
109
114
 
110
115
  // Verify update
111
- const results = await vectorDB.query(testIndexName, updatedVector?.[0]!, 1);
116
+ const results = await vectorDB.query({ indexName: testIndexName, queryVector: updatedVector?.[0]!, topK: 1 });
112
117
  expect(results?.[0]?.id).toBe(testIds[0]);
113
118
  expect(results?.[0]?.metadata).toEqual(updatedMetadata[0]);
114
119
  });
@@ -124,7 +129,7 @@ describe('ChromaVector Integration Tests', () => {
124
129
  const testIds = ['vec1', 'vec2', 'vec3'];
125
130
 
126
131
  beforeEach(async () => {
127
- await vectorDB.upsert(testIndexName, testVectors, testMetadata, testIds);
132
+ await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors, metadata: testMetadata, ids: testIds });
128
133
  });
129
134
 
130
135
  describe('Basic Queries', () => {
@@ -132,7 +137,7 @@ describe('ChromaVector Integration Tests', () => {
132
137
  const queryVector = [1.0, 0.1, 0.1];
133
138
  const topK = 2;
134
139
 
135
- const results: QueryResult[] = await vectorDB.query(testIndexName, queryVector, topK);
140
+ const results: QueryResult[] = await vectorDB.query({ indexName: testIndexName, queryVector, topK });
136
141
 
137
142
  expect(results).toHaveLength(topK);
138
143
  expect(results?.[0]?.id).toBe(testIds[0]); // Should match x-axis vector most closely
@@ -144,7 +149,7 @@ describe('ChromaVector Integration Tests', () => {
144
149
  const queryVector = [1.0, 1.0, 1.0];
145
150
  const filter = { label: 'x-axis' };
146
151
 
147
- const results = await vectorDB.query(testIndexName, queryVector, 3, filter);
152
+ const results = await vectorDB.query({ indexName: testIndexName, queryVector, topK: 3, filter });
148
153
 
149
154
  expect(results).toHaveLength(1);
150
155
  expect(results?.[0]?.metadata?.label).toBe('x-axis');
@@ -156,7 +161,12 @@ describe('ChromaVector Integration Tests', () => {
156
161
  const queryVector = [1.0, 0.1, 0.1];
157
162
  const topK = 1;
158
163
 
159
- const results = await vectorDB.query(testIndexName, queryVector, topK, undefined, true);
164
+ const results = await vectorDB.query({
165
+ indexName: testIndexName,
166
+ queryVector,
167
+ topK,
168
+ includeVector: true,
169
+ });
160
170
 
161
171
  expect(results).toHaveLength(topK);
162
172
  expect(results?.[0]?.vector).toEqual(testVectors[0]);
@@ -166,73 +176,95 @@ describe('ChromaVector Integration Tests', () => {
166
176
 
167
177
  describe('Error Handling', () => {
168
178
  it('should handle non-existent index queries', async () => {
169
- await expect(vectorDB.query('non-existent-index-yu', [1, 2, 3])).rejects.toThrow();
179
+ await expect(vectorDB.query({ indexName: 'non-existent-index-yu', queryVector: [1, 2, 3] })).rejects.toThrow();
170
180
  });
171
181
 
172
182
  it('should handle invalid dimension vectors', async () => {
173
183
  const invalidVector = [1, 2, 3, 4]; // 4D vector for 3D index
174
- await expect(vectorDB.upsert(testIndexName, [invalidVector])).rejects.toThrow();
184
+ await expect(vectorDB.upsert({ indexName: testIndexName, vectors: [invalidVector] })).rejects.toThrow();
175
185
  });
176
186
 
177
187
  it('should handle mismatched metadata and vectors length', async () => {
178
188
  const vectors = [[1, 2, 3]];
179
189
  const metadata = [{}, {}]; // More metadata than vectors
180
- await expect(vectorDB.upsert(testIndexName, vectors, metadata)).rejects.toThrow();
190
+ await expect(vectorDB.upsert({ indexName: testIndexName, vectors, metadata })).rejects.toThrow();
181
191
  });
182
192
  });
183
193
 
184
194
  describe('Filter Validation in Queries', () => {
185
195
  it('rejects queries with null values', async () => {
186
196
  await expect(
187
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
188
- field: null,
197
+ vectorDB.query({
198
+ indexName: testIndexName,
199
+ queryVector: [1, 0, 0],
200
+ filter: {
201
+ field: null,
202
+ },
189
203
  }),
190
204
  ).rejects.toThrow();
191
205
 
192
206
  await expect(
193
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
194
- other: { $eq: null },
207
+ vectorDB.query({
208
+ indexName: testIndexName,
209
+ queryVector: [1, 0, 0],
210
+ filter: {
211
+ other: { $eq: null },
212
+ },
195
213
  }),
196
214
  ).rejects.toThrow();
197
215
  });
198
216
 
199
217
  it('validates array operator values', async () => {
200
218
  await expect(
201
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
202
- tags: { $in: null },
219
+ vectorDB.query({
220
+ indexName: testIndexName,
221
+ queryVector: [1, 0, 0],
222
+ filter: {
223
+ tags: { $in: null },
224
+ },
203
225
  }),
204
226
  ).rejects.toThrow();
205
227
  });
206
228
 
207
229
  it('validates numeric values for comparison operators', async () => {
208
230
  await expect(
209
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
210
- price: { $gt: 'not-a-number' },
231
+ vectorDB.query({
232
+ indexName: testIndexName,
233
+ queryVector: [1, 0, 0],
234
+ filter: {
235
+ price: { $gt: 'not-a-number' },
236
+ },
211
237
  }),
212
238
  ).rejects.toThrow();
213
239
  });
214
240
 
215
241
  it('validates value types', async () => {
216
242
  await expect(
217
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
218
- date: { $gt: 'not-a-date' },
243
+ vectorDB.query({
244
+ indexName: testIndexName,
245
+ queryVector: [1, 0, 0],
246
+ filter: { date: { $gt: 'not-a-date' } },
219
247
  }),
220
248
  ).rejects.toThrow();
221
249
 
222
250
  await expect(
223
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
224
- number: { $lt: 'not-a-number' },
251
+ vectorDB.query({
252
+ indexName: testIndexName,
253
+ queryVector: [1, 0, 0],
254
+ filter: { number: { $lt: 'not-a-number' } },
225
255
  }),
226
256
  ).rejects.toThrow();
227
257
  });
228
258
 
229
259
  it('validates array operators', async () => {
230
- const invalidValues = [123, 'string', true, { key: 'value' }, null, undefined];
260
+ const invalidValues = [123, 'string', true, { key: 'value' }, null];
231
261
  for (const op of ['$in', '$nin']) {
232
262
  for (const val of invalidValues) {
233
263
  await expect(
234
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
235
- field: { [op]: val },
264
+ vectorDB.query({
265
+ indexName: testIndexName,
266
+ queryVector: [1, 0, 0],
267
+ filter: { field: { [op]: val } },
236
268
  }),
237
269
  ).rejects.toThrow();
238
270
  }
@@ -245,8 +277,10 @@ describe('ChromaVector Integration Tests', () => {
245
277
  for (const op of ['$in', '$nin']) {
246
278
  for (const val of invalidValues) {
247
279
  await expect(
248
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
249
- field: { [op]: val },
280
+ vectorDB.query({
281
+ indexName: testIndexName,
282
+ queryVector: [1, 0, 0],
283
+ filter: { field: { [op]: val } },
250
284
  }),
251
285
  ).rejects.toThrow();
252
286
  }
@@ -257,8 +291,10 @@ describe('ChromaVector Integration Tests', () => {
257
291
  // Basic equality can accept any non-undefined value
258
292
  for (const op of ['$eq', '$ne']) {
259
293
  await expect(
260
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
261
- field: { [op]: undefined },
294
+ vectorDB.query({
295
+ indexName: testIndexName,
296
+ queryVector: [1, 0, 0],
297
+ filter: { field: { [op]: undefined } },
262
298
  }),
263
299
  ).rejects.toThrow();
264
300
  }
@@ -269,8 +305,10 @@ describe('ChromaVector Integration Tests', () => {
269
305
  for (const op of numOps) {
270
306
  for (const val of invalidNumericValues) {
271
307
  await expect(
272
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
273
- field: { [op]: val },
308
+ vectorDB.query({
309
+ indexName: testIndexName,
310
+ queryVector: [1, 0, 0],
311
+ filter: { field: { [op]: val } },
274
312
  }),
275
313
  ).rejects.toThrow();
276
314
  }
@@ -279,29 +317,45 @@ describe('ChromaVector Integration Tests', () => {
279
317
 
280
318
  it('validates multiple invalid values', async () => {
281
319
  await expect(
282
- vectorDB.query(testIndexName, [1, 0, 0], 10, {
283
- field1: { $in: 'not-array' },
284
- field2: { $exists: 'not-boolean' },
285
- field3: { $gt: 'not-number' },
320
+ vectorDB.query({
321
+ indexName: testIndexName,
322
+ queryVector: [1, 0, 0],
323
+ filter: {
324
+ field1: { $in: 'not-array' },
325
+ field2: { $exists: 'not-boolean' },
326
+ field3: { $gt: 'not-number' },
327
+ },
286
328
  }),
287
329
  ).rejects.toThrow();
288
330
  });
289
331
 
290
332
  it('handles empty object filters', async () => {
291
333
  // Test empty object at top level
292
- await expect(vectorDB.query(testIndexName, [1, 0, 0], 10, { field: { $eq: {} } })).rejects.toThrow();
334
+ await expect(
335
+ vectorDB.query({
336
+ indexName: testIndexName,
337
+ queryVector: [1, 0, 0],
338
+ filter: { field: { $eq: {} } },
339
+ }),
340
+ ).rejects.toThrow();
293
341
  });
294
342
 
295
343
  it('handles empty/undefined filters by returning all results', async () => {
296
344
  const noFilterCases = [{ field: {} }, { field: undefined }, { field: { $in: undefined } }];
297
345
 
298
346
  for (const filter of noFilterCases) {
299
- await expect(vectorDB.query(testIndexName, [1, 0, 0], 10, filter)).rejects.toThrow();
347
+ await expect(vectorDB.query({ indexName: testIndexName, queryVector: [1, 0, 0], filter })).rejects.toThrow();
300
348
  }
301
349
  });
302
350
  it('handles empty object filters', async () => {
303
351
  // Test empty object at top level
304
- await expect(vectorDB.query(testIndexName, [1, 0, 0], 10, {})).rejects.toThrow();
352
+ await expect(
353
+ vectorDB.query({
354
+ indexName: testIndexName,
355
+ queryVector: [1, 0, 0],
356
+ filter: {},
357
+ }),
358
+ ).rejects.toThrow();
305
359
  });
306
360
  });
307
361
 
@@ -313,7 +367,7 @@ describe('ChromaVector Integration Tests', () => {
313
367
  } catch {
314
368
  // Ignore errors if index doesn't exist
315
369
  }
316
- await vectorDB.createIndex(testIndexName2, dimension);
370
+ await vectorDB.createIndex({ indexName: testIndexName2, dimension });
317
371
 
318
372
  const vectors = [
319
373
  [1, 0, 0], // Electronics
@@ -349,7 +403,7 @@ describe('ChromaVector Integration Tests', () => {
349
403
  },
350
404
  ];
351
405
 
352
- await vectorDB.upsert(testIndexName2, vectors, metadata);
406
+ await vectorDB.upsert({ indexName: testIndexName2, vectors, metadata });
353
407
  // Wait for indexing
354
408
  await new Promise(resolve => setTimeout(resolve, 2000));
355
409
  });
@@ -365,8 +419,10 @@ describe('ChromaVector Integration Tests', () => {
365
419
 
366
420
  describe('Basic Comparison Operators', () => {
367
421
  it('filters with $eq operator', async () => {
368
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
369
- category: { $eq: 'electronics' },
422
+ const results = await vectorDB.query({
423
+ indexName: testIndexName2,
424
+ queryVector: [1, 0, 0],
425
+ filter: { category: { $eq: 'electronics' } },
370
426
  });
371
427
  expect(results.length).toBe(2);
372
428
  results.forEach(result => {
@@ -375,8 +431,10 @@ describe('ChromaVector Integration Tests', () => {
375
431
  });
376
432
 
377
433
  it('filters with implicit $eq', async () => {
378
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
379
- category: 'electronics', // implicit $eq
434
+ const results = await vectorDB.query({
435
+ indexName: testIndexName2,
436
+ queryVector: [1, 0, 0],
437
+ filter: { category: 'electronics' }, // implicit $eq
380
438
  });
381
439
  expect(results.length).toBe(2);
382
440
  results.forEach(result => {
@@ -384,8 +442,10 @@ describe('ChromaVector Integration Tests', () => {
384
442
  });
385
443
  });
386
444
  it('filters with $gt operator', async () => {
387
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
388
- price: { $gt: 500 },
445
+ const results = await vectorDB.query({
446
+ indexName: testIndexName2,
447
+ queryVector: [1, 0, 0],
448
+ filter: { price: { $gt: 500 } },
389
449
  });
390
450
  expect(results.length).toBe(1);
391
451
  results.forEach(result => {
@@ -394,8 +454,10 @@ describe('ChromaVector Integration Tests', () => {
394
454
  });
395
455
 
396
456
  it('filters with $gte operator', async () => {
397
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
398
- price: { $gte: 500 },
457
+ const results = await vectorDB.query({
458
+ indexName: testIndexName2,
459
+ queryVector: [1, 0, 0],
460
+ filter: { price: { $gte: 500 } },
399
461
  });
400
462
  expect(results.length).toBe(2);
401
463
  results.forEach(result => {
@@ -404,8 +466,10 @@ describe('ChromaVector Integration Tests', () => {
404
466
  });
405
467
 
406
468
  it('filters with $lt operator', async () => {
407
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
408
- price: { $lt: 100 },
469
+ const results = await vectorDB.query({
470
+ indexName: testIndexName2,
471
+ queryVector: [1, 0, 0],
472
+ filter: { price: { $lt: 100 } },
409
473
  });
410
474
  expect(results.length).toBe(2);
411
475
  results.forEach(result => {
@@ -414,8 +478,10 @@ describe('ChromaVector Integration Tests', () => {
414
478
  });
415
479
 
416
480
  it('filters with $lte operator', async () => {
417
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
418
- price: { $lte: 500 },
481
+ const results = await vectorDB.query({
482
+ indexName: testIndexName2,
483
+ queryVector: [1, 0, 0],
484
+ filter: { price: { $lte: 500 } },
419
485
  });
420
486
  expect(results.length).toBeGreaterThan(0);
421
487
  results.forEach(result => {
@@ -424,8 +490,10 @@ describe('ChromaVector Integration Tests', () => {
424
490
  });
425
491
 
426
492
  it('filters with $gte, $lt, $lte operators', async () => {
427
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
428
- price: { $gte: 25, $lte: 500 },
493
+ const results = await vectorDB.query({
494
+ indexName: testIndexName2,
495
+ queryVector: [1, 0, 0],
496
+ filter: { price: { $gte: 25, $lte: 500 } },
429
497
  });
430
498
  expect(results.length).toBe(2);
431
499
  results.forEach(result => {
@@ -435,8 +503,10 @@ describe('ChromaVector Integration Tests', () => {
435
503
  });
436
504
 
437
505
  it('filters with $ne operator', async () => {
438
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
439
- category: { $ne: 'electronics' },
506
+ const results = await vectorDB.query({
507
+ indexName: testIndexName2,
508
+ queryVector: [1, 0, 0],
509
+ filter: { category: { $ne: 'electronics' } },
440
510
  });
441
511
  expect(results.length).toBe(2);
442
512
  results.forEach(result => {
@@ -445,8 +515,10 @@ describe('ChromaVector Integration Tests', () => {
445
515
  });
446
516
 
447
517
  it('filters with boolean values', async () => {
448
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
449
- inStock: true, // test both implicit
518
+ const results = await vectorDB.query({
519
+ indexName: testIndexName2,
520
+ queryVector: [1, 0, 0],
521
+ filter: { inStock: true }, // test both implicit
450
522
  });
451
523
  expect(results.length).toBe(3);
452
524
  results.forEach(result => {
@@ -455,9 +527,10 @@ describe('ChromaVector Integration Tests', () => {
455
527
  });
456
528
 
457
529
  it('filters with multiple fields', async () => {
458
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
459
- category: 'electronics',
460
- price: 1000,
530
+ const results = await vectorDB.query({
531
+ indexName: testIndexName2,
532
+ queryVector: [1, 0, 0],
533
+ filter: { category: 'electronics', price: 1000 },
461
534
  });
462
535
  expect(results.length).toBeGreaterThan(0);
463
536
  results.forEach(result => {
@@ -468,8 +541,10 @@ describe('ChromaVector Integration Tests', () => {
468
541
 
469
542
  describe('Array Operators', () => {
470
543
  it('filters with $in operator', async () => {
471
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
472
- category: { $in: ['electronics', 'books'] },
544
+ const results = await vectorDB.query({
545
+ indexName: testIndexName2,
546
+ queryVector: [1, 0, 0],
547
+ filter: { category: { $in: ['electronics', 'books'] } },
473
548
  });
474
549
  expect(results.length).toBeGreaterThan(0);
475
550
  results.forEach(result => {
@@ -478,8 +553,10 @@ describe('ChromaVector Integration Tests', () => {
478
553
  });
479
554
 
480
555
  it('should filter with $in operator for numbers', async () => {
481
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
482
- price: { $in: [50, 75, 1000] },
556
+ const results = await vectorDB.query({
557
+ indexName: testIndexName2,
558
+ queryVector: [1, 0, 0],
559
+ filter: { price: { $in: [50, 75, 1000] } },
483
560
  });
484
561
  expect(results.length).toBeGreaterThan(0);
485
562
  results.forEach(result => {
@@ -488,8 +565,10 @@ describe('ChromaVector Integration Tests', () => {
488
565
  });
489
566
 
490
567
  it('filters with $in operator for booleans', async () => {
491
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
492
- inStock: { $in: [true] },
568
+ const results = await vectorDB.query({
569
+ indexName: testIndexName2,
570
+ queryVector: [1, 0, 0],
571
+ filter: { inStock: { $in: [true] } },
493
572
  });
494
573
  expect(results.length).toBeGreaterThan(0);
495
574
  results.forEach(result => {
@@ -500,8 +579,10 @@ describe('ChromaVector Integration Tests', () => {
500
579
 
501
580
  describe('Logical Operators', () => {
502
581
  it('filters with $and operator', async () => {
503
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
504
- $and: [{ category: 'electronics' }, { price: { $gt: 500 } }],
582
+ const results = await vectorDB.query({
583
+ indexName: testIndexName2,
584
+ queryVector: [1, 0, 0],
585
+ filter: { $and: [{ category: 'electronics' }, { price: { $gt: 500 } }] },
505
586
  });
506
587
  expect(results.length).toBe(1);
507
588
  expect(results[0]?.metadata?.category).toBe('electronics');
@@ -509,8 +590,10 @@ describe('ChromaVector Integration Tests', () => {
509
590
  });
510
591
 
511
592
  it('should filter with $and operator', async () => {
512
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
513
- $and: [{ category: 'electronics' }, { price: { $gt: 700 } }, { inStock: true }],
593
+ const results = await vectorDB.query({
594
+ indexName: testIndexName2,
595
+ queryVector: [1, 0, 0],
596
+ filter: { $and: [{ category: 'electronics' }, { price: { $gt: 700 } }, { inStock: true }] },
514
597
  });
515
598
  expect(results.length).toBeGreaterThan(0);
516
599
  results.forEach(result => {
@@ -521,8 +604,10 @@ describe('ChromaVector Integration Tests', () => {
521
604
  });
522
605
 
523
606
  it('filters with $or operator', async () => {
524
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
525
- $or: [{ price: { $gt: 900 } }, { rating: { $gt: 4.8 } }],
607
+ const results = await vectorDB.query({
608
+ indexName: testIndexName2,
609
+ queryVector: [1, 0, 0],
610
+ filter: { $or: [{ price: { $gt: 900 } }, { rating: { $gt: 4.8 } }] },
526
611
  });
527
612
  expect(results.length).toBe(2);
528
613
  results.forEach(result => {
@@ -531,8 +616,10 @@ describe('ChromaVector Integration Tests', () => {
531
616
  });
532
617
 
533
618
  it('should filter with $or operator', async () => {
534
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
535
- $or: [{ price: { $gt: 900 } }, { category: { $in: ['electronics', 'books'] } }],
619
+ const results = await vectorDB.query({
620
+ indexName: testIndexName2,
621
+ queryVector: [1, 0, 0],
622
+ filter: { $or: [{ price: { $gt: 900 } }, { category: { $in: ['electronics', 'books'] } }] },
536
623
  });
537
624
  expect(results.length).toBeGreaterThan(0);
538
625
  results.forEach(result => {
@@ -543,14 +630,18 @@ describe('ChromaVector Integration Tests', () => {
543
630
  });
544
631
 
545
632
  it('should handle nested logical operators', async () => {
546
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
547
- $and: [
548
- {
549
- $or: [{ category: 'electronics' }, { category: 'books' }],
550
- },
551
- { price: { $lt: 100 } },
552
- { inStock: true },
553
- ],
633
+ const results = await vectorDB.query({
634
+ indexName: testIndexName2,
635
+ queryVector: [1, 0, 0],
636
+ filter: {
637
+ $and: [
638
+ {
639
+ $or: [{ category: 'electronics' }, { category: 'books' }],
640
+ },
641
+ { price: { $lt: 100 } },
642
+ { inStock: true },
643
+ ],
644
+ },
554
645
  });
555
646
  expect(results.length).toBeGreaterThan(0);
556
647
  results.forEach(result => {
@@ -561,22 +652,28 @@ describe('ChromaVector Integration Tests', () => {
561
652
  });
562
653
 
563
654
  it('uses implicit $eq within $or', async () => {
564
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
565
- $or: [{ category: 'electronics' }, { price: { $gt: 100 } }],
655
+ const results = await vectorDB.query({
656
+ indexName: testIndexName2,
657
+ queryVector: [1, 0, 0],
658
+ filter: { $or: [{ category: 'electronics' }, { price: { $gt: 100 } }] },
566
659
  });
567
660
  expect(results.length).toBeGreaterThan(0);
568
661
  });
569
662
 
570
663
  it('requires multiple conditions in logical operators', async () => {
571
664
  await expect(
572
- vectorDB.query(testIndexName2, [1, 0, 0], 10, {
573
- $and: [{ category: 'electronics' }],
665
+ vectorDB.query({
666
+ indexName: testIndexName2,
667
+ queryVector: [1, 0, 0],
668
+ filter: { $and: [{ category: 'electronics' }] },
574
669
  }),
575
670
  ).rejects.toThrow();
576
671
 
577
672
  await expect(
578
- vectorDB.query(testIndexName2, [1, 0, 0], 10, {
579
- $or: [{ price: { $gt: 900 } }],
673
+ vectorDB.query({
674
+ indexName: testIndexName2,
675
+ queryVector: [1, 0, 0],
676
+ filter: { $or: [{ price: { $gt: 900 } }] },
580
677
  }),
581
678
  ).rejects.toThrow();
582
679
  });
@@ -584,14 +681,18 @@ describe('ChromaVector Integration Tests', () => {
584
681
 
585
682
  describe('Complex Filter Combinations', () => {
586
683
  it('combines multiple operators and conditions', async () => {
587
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
588
- $and: [
589
- { price: { $gt: 20 } },
590
- { inStock: true },
591
- {
592
- $or: [{ category: { $in: ['books'] } }, { rating: { $gt: 4.5 } }],
593
- },
594
- ],
684
+ const results = await vectorDB.query({
685
+ indexName: testIndexName2,
686
+ queryVector: [1, 0, 0],
687
+ filter: {
688
+ $and: [
689
+ { price: { $gt: 20 } },
690
+ { inStock: true },
691
+ {
692
+ $or: [{ category: { $in: ['books'] } }, { rating: { $gt: 4.5 } }],
693
+ },
694
+ ],
695
+ },
595
696
  });
596
697
  expect(results.length).toBeGreaterThan(0);
597
698
  results.forEach(result => {
@@ -602,15 +703,19 @@ describe('ChromaVector Integration Tests', () => {
602
703
  });
603
704
 
604
705
  it('handles complex nested conditions', async () => {
605
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
606
- $or: [
607
- {
608
- $and: [{ category: 'electronics' }, { price: { $gt: 700 } }],
609
- },
610
- {
611
- $and: [{ category: 'books' }, { price: { $lt: 20 } }],
612
- },
613
- ],
706
+ const results = await vectorDB.query({
707
+ indexName: testIndexName2,
708
+ queryVector: [1, 0, 0],
709
+ filter: {
710
+ $or: [
711
+ {
712
+ $and: [{ category: 'electronics' }, { price: { $gt: 700 } }],
713
+ },
714
+ {
715
+ $and: [{ category: 'books' }, { price: { $lt: 20 } }],
716
+ },
717
+ ],
718
+ },
614
719
  });
615
720
  expect(results.length).toBeGreaterThan(0);
616
721
  results.forEach(result => {
@@ -623,8 +728,10 @@ describe('ChromaVector Integration Tests', () => {
623
728
  });
624
729
 
625
730
  it('should combine comparison and array operators', async () => {
626
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
627
- $and: [{ price: { $gte: 500 } }, { rating: { $gt: 4.5 } }],
731
+ const results = await vectorDB.query({
732
+ indexName: testIndexName2,
733
+ queryVector: [1, 0, 0],
734
+ filter: { $and: [{ price: { $gte: 500 } }, { rating: { $gt: 4.5 } }] },
628
735
  });
629
736
  expect(results.length).toBeGreaterThan(0);
630
737
  results.forEach(result => {
@@ -634,8 +741,10 @@ describe('ChromaVector Integration Tests', () => {
634
741
  });
635
742
 
636
743
  it('should handle multiple conditions on same field', async () => {
637
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
638
- $and: [{ price: { $gte: 30 } }, { price: { $lte: 800 } }],
744
+ const results = await vectorDB.query({
745
+ indexName: testIndexName2,
746
+ queryVector: [1, 0, 0],
747
+ filter: { $and: [{ price: { $gte: 30 } }, { price: { $lte: 800 } }] },
639
748
  });
640
749
  expect(results.length).toBeGreaterThan(0);
641
750
  results.forEach(result => {
@@ -646,15 +755,19 @@ describe('ChromaVector Integration Tests', () => {
646
755
  });
647
756
 
648
757
  it('should handle deeply nested logical operators', async () => {
649
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
650
- $or: [
651
- {
652
- $and: [{ category: 'electronics' }, { price: { $gt: 700 } }, { rating: { $gt: 4.5 } }],
653
- },
654
- {
655
- $and: [{ category: 'books' }, { price: { $lt: 50 } }, { rating: { $gt: 4.0 } }],
656
- },
657
- ],
758
+ const results = await vectorDB.query({
759
+ indexName: testIndexName2,
760
+ queryVector: [1, 0, 0],
761
+ filter: {
762
+ $or: [
763
+ {
764
+ $and: [{ category: 'electronics' }, { price: { $gt: 700 } }, { rating: { $gt: 4.5 } }],
765
+ },
766
+ {
767
+ $and: [{ category: 'books' }, { price: { $lt: 50 } }, { rating: { $gt: 4.0 } }],
768
+ },
769
+ ],
770
+ },
658
771
  });
659
772
  expect(results.length).toBeGreaterThan(0);
660
773
  results.forEach(result => {
@@ -702,13 +815,19 @@ describe('ChromaVector Integration Tests', () => {
702
815
  },
703
816
  ];
704
817
 
705
- await vectorDB.upsert(testIndexName2, vectors, metadata);
818
+ await vectorDB.upsert({
819
+ indexName: testIndexName2,
820
+ vectors,
821
+ metadata,
822
+ });
706
823
  await new Promise(resolve => setTimeout(resolve, 2000));
707
824
  });
708
825
 
709
826
  it('handles special numeric values', async () => {
710
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
711
- $or: [{ zero: 0 }, { negativeZero: 0 }],
827
+ const results = await vectorDB.query({
828
+ indexName: testIndexName2,
829
+ queryVector: [1, 0, 0],
830
+ filter: { $or: [{ zero: 0 }, { negativeZero: 0 }] },
712
831
  });
713
832
  expect(results.length).toBeGreaterThan(0);
714
833
  results.forEach(result => {
@@ -718,15 +837,23 @@ describe('ChromaVector Integration Tests', () => {
718
837
  });
719
838
 
720
839
  it('handles extreme numeric values', async () => {
721
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
722
- $or: [{ maxInt: { $gte: Number.MAX_SAFE_INTEGER } }, { minInt: { $lte: Number.MIN_SAFE_INTEGER } }],
840
+ const results = await vectorDB.query({
841
+ indexName: testIndexName2,
842
+ queryVector: [1, 0, 0],
843
+ filter: {
844
+ $or: [{ maxInt: { $gte: Number.MAX_SAFE_INTEGER } }, { minInt: { $lte: Number.MIN_SAFE_INTEGER } }],
845
+ },
723
846
  });
724
847
  expect(results.length).toBe(1);
725
848
  });
726
849
 
727
850
  it('should handle numeric comparisons with decimals', async () => {
728
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
729
- rating: { $gt: 4.5 },
851
+ const results = await vectorDB.query({
852
+ indexName: testIndexName2,
853
+ queryVector: [1, 0, 0],
854
+ filter: {
855
+ rating: { $gt: 4.5 },
856
+ },
730
857
  });
731
858
  expect(results.length).toBeGreaterThan(0);
732
859
  results.forEach(result => {
@@ -735,8 +862,10 @@ describe('ChromaVector Integration Tests', () => {
735
862
  });
736
863
 
737
864
  it('should handle boolean values', async () => {
738
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
739
- inStock: { $eq: false },
865
+ const results = await vectorDB.query({
866
+ indexName: testIndexName2,
867
+ queryVector: [1, 0, 0],
868
+ filter: { inStock: { $eq: false } },
740
869
  });
741
870
  expect(results.length).toBeGreaterThan(0);
742
871
  results.forEach(result => {
@@ -748,46 +877,78 @@ describe('ChromaVector Integration Tests', () => {
748
877
  describe('Additional Validation Tests', () => {
749
878
  it('should throw error as date is not supported', async () => {
750
879
  await expect(
751
- vectorDB.query(testIndexName2, [1, 0, 0], 10, {
752
- $and: [
753
- { currentDate: { $lte: new Date().toISOString() } },
754
- { currentDate: { $gt: new Date(0).toISOString() } },
755
- ],
880
+ vectorDB.query({
881
+ indexName: testIndexName2,
882
+ queryVector: [1, 0, 0],
883
+ filter: {
884
+ $and: [
885
+ { currentDate: { $lte: new Date().toISOString() } },
886
+ { currentDate: { $gt: new Date(0).toISOString() } },
887
+ ],
888
+ },
756
889
  }),
757
890
  ).rejects.toThrow();
758
891
  });
759
892
  it('should throw error as empty array in $in operator is not supported', async () => {
760
893
  await expect(
761
- vectorDB.query(testIndexName2, [1, 0, 0], 10, {
762
- category: { $in: [] },
894
+ vectorDB.query({
895
+ indexName: testIndexName2,
896
+ queryVector: [1, 0, 0],
897
+ filter: {
898
+ category: { $in: [] },
899
+ },
763
900
  }),
764
901
  ).rejects.toThrow();
765
902
  });
766
903
  it('should reject non-numeric values in numeric comparisons', async () => {
767
904
  await expect(
768
- vectorDB.query(testIndexName2, [1, 0, 0], 10, {
769
- price: { $gt: '500' }, // string instead of number
905
+ vectorDB.query({
906
+ indexName: testIndexName2,
907
+ queryVector: [1, 0, 0],
908
+ filter: {
909
+ price: { $gt: '500' }, // string instead of number
910
+ },
770
911
  }),
771
912
  ).rejects.toThrow();
772
913
  });
773
914
 
774
915
  it('should reject mixed types in $in operator', async () => {
775
916
  await expect(
776
- vectorDB.query(testIndexName2, [1, 0, 0], 10, {
777
- field: { $in: ['string', 123] }, // mixed string and number
917
+ vectorDB.query({
918
+ indexName: testIndexName2,
919
+ queryVector: [1, 0, 0],
920
+ filter: {
921
+ field: { $in: ['string', 123] }, // mixed string and number
922
+ },
778
923
  }),
779
924
  ).rejects.toThrow();
780
925
  });
781
926
  it('should handle undefined filter', async () => {
782
- const results1 = await vectorDB.query(testIndexName2, [1, 0, 0], 10, undefined);
783
- const results2 = await vectorDB.query(testIndexName2, [1, 0, 0], 10);
927
+ const results1 = await vectorDB.query({
928
+ indexName: testIndexName2,
929
+ queryVector: [1, 0, 0],
930
+ filter: undefined,
931
+ });
932
+ const results2 = await vectorDB.query({
933
+ indexName: testIndexName2,
934
+ queryVector: [1, 0, 0],
935
+ filter: undefined,
936
+ });
784
937
  expect(results1).toEqual(results2);
785
938
  expect(results1.length).toBeGreaterThan(0);
786
939
  });
787
940
 
788
941
  it('should handle null filter', async () => {
789
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, null as any);
790
- const results2 = await vectorDB.query(testIndexName2, [1, 0, 0], 10);
942
+ const results = await vectorDB.query({
943
+ indexName: testIndexName2,
944
+ queryVector: [1, 0, 0],
945
+ filter: null,
946
+ });
947
+ const results2 = await vectorDB.query({
948
+ indexName: testIndexName2,
949
+ queryVector: [1, 0, 0],
950
+ filter: undefined,
951
+ });
791
952
  expect(results).toEqual(results2);
792
953
  expect(results.length).toBeGreaterThan(0);
793
954
  });
@@ -795,8 +956,12 @@ describe('ChromaVector Integration Tests', () => {
795
956
 
796
957
  describe('Additional Edge Cases', () => {
797
958
  it('should handle exact boundary conditions', async () => {
798
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
799
- $and: [{ price: { $gte: 25 } }, { price: { $lte: 1000 } }],
959
+ const results = await vectorDB.query({
960
+ indexName: testIndexName2,
961
+ queryVector: [1, 0, 0],
962
+ filter: {
963
+ $and: [{ price: { $gte: 25 } }, { price: { $lte: 1000 } }],
964
+ },
800
965
  });
801
966
  expect(results.length).toBeGreaterThan(0);
802
967
  expect(results.some(r => r.metadata?.price === 25)).toBe(true);
@@ -806,15 +971,19 @@ describe('ChromaVector Integration Tests', () => {
806
971
 
807
972
  describe('Additional Complex Logical Combinations', () => {
808
973
  it('should handle deeply nested $or conditions', async () => {
809
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
810
- $or: [
811
- {
812
- $and: [{ category: 'electronics' }, { $or: [{ price: { $gt: 900 } }, { rating: { $gt: 4.8 } }] }],
813
- },
814
- {
815
- $and: [{ category: 'books' }, { $or: [{ price: { $lt: 30 } }, { rating: { $gt: 4.5 } }] }],
816
- },
817
- ],
974
+ const results = await vectorDB.query({
975
+ indexName: testIndexName2,
976
+ queryVector: [1, 0, 0],
977
+ filter: {
978
+ $or: [
979
+ {
980
+ $and: [{ category: 'electronics' }, { $or: [{ price: { $gt: 900 } }, { rating: { $gt: 4.8 } }] }],
981
+ },
982
+ {
983
+ $and: [{ category: 'books' }, { $or: [{ price: { $lt: 30 } }, { rating: { $gt: 4.5 } }] }],
984
+ },
985
+ ],
986
+ },
818
987
  });
819
988
  expect(results.length).toBeGreaterThan(0);
820
989
  results.forEach(result => {
@@ -827,8 +996,12 @@ describe('ChromaVector Integration Tests', () => {
827
996
  });
828
997
 
829
998
  it('should handle multiple field comparisons with same value', async () => {
830
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
831
- $or: [{ price: { $gt: 500 } }, { rating: { $gt: 4.5 } }],
999
+ const results = await vectorDB.query({
1000
+ indexName: testIndexName2,
1001
+ queryVector: [1, 0, 0],
1002
+ filter: {
1003
+ $or: [{ price: { $gt: 500 } }, { rating: { $gt: 4.5 } }],
1004
+ },
832
1005
  });
833
1006
  expect(results.length).toBeGreaterThan(0);
834
1007
  results.forEach(result => {
@@ -839,12 +1012,16 @@ describe('ChromaVector Integration Tests', () => {
839
1012
 
840
1013
  describe('Performance Edge Cases', () => {
841
1014
  it('should handle filters with many conditions', async () => {
842
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
843
- $and: Array(10)
844
- .fill(null)
845
- .map(() => ({
846
- $or: [{ price: { $gt: 100 } }, { rating: { $gt: 4.0 } }],
847
- })),
1015
+ const results = await vectorDB.query({
1016
+ indexName: testIndexName2,
1017
+ queryVector: [1, 0, 0],
1018
+ filter: {
1019
+ $and: Array(10)
1020
+ .fill(null)
1021
+ .map(() => ({
1022
+ $or: [{ price: { $gt: 100 } }, { rating: { $gt: 4.0 } }],
1023
+ })),
1024
+ },
848
1025
  });
849
1026
  expect(results.length).toBeGreaterThan(0);
850
1027
  results.forEach(result => {
@@ -853,12 +1030,20 @@ describe('ChromaVector Integration Tests', () => {
853
1030
  });
854
1031
 
855
1032
  it('should handle deeply nested conditions efficiently', async () => {
856
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
857
- $or: Array(5)
858
- .fill(null)
859
- .map(() => ({
860
- $and: [{ category: { $in: ['electronics', 'books'] } }, { price: { $gt: 50 } }, { rating: { $gt: 4.0 } }],
861
- })),
1033
+ const results = await vectorDB.query({
1034
+ indexName: testIndexName2,
1035
+ queryVector: [1, 0, 0],
1036
+ filter: {
1037
+ $or: Array(5)
1038
+ .fill(null)
1039
+ .map(() => ({
1040
+ $and: [
1041
+ { category: { $in: ['electronics', 'books'] } },
1042
+ { price: { $gt: 50 } },
1043
+ { rating: { $gt: 4.0 } },
1044
+ ],
1045
+ })),
1046
+ },
862
1047
  });
863
1048
  expect(results.length).toBeGreaterThan(0);
864
1049
  results.forEach(result => {
@@ -869,19 +1054,23 @@ describe('ChromaVector Integration Tests', () => {
869
1054
  });
870
1055
 
871
1056
  it('should handle large number of $or conditions', async () => {
872
- const results = await vectorDB.query(testIndexName2, [1, 0, 0], 10, {
873
- $or: [
874
- ...Array(5)
875
- .fill(null)
876
- .map((_, i) => ({
877
- price: { $gt: i * 100 },
878
- })),
879
- ...Array(5)
880
- .fill(null)
881
- .map((_, i) => ({
882
- rating: { $gt: 4.0 + i * 0.1 },
883
- })),
884
- ],
1057
+ const results = await vectorDB.query({
1058
+ indexName: testIndexName2,
1059
+ queryVector: [1, 0, 0],
1060
+ filter: {
1061
+ $or: [
1062
+ ...Array(5)
1063
+ .fill(null)
1064
+ .map((_, i) => ({
1065
+ price: { $gt: i * 100 },
1066
+ })),
1067
+ ...Array(5)
1068
+ .fill(null)
1069
+ .map((_, i) => ({
1070
+ rating: { $gt: 4.0 + i * 0.1 },
1071
+ })),
1072
+ ],
1073
+ },
885
1074
  });
886
1075
  expect(results.length).toBeGreaterThan(0);
887
1076
  });
@@ -901,7 +1090,7 @@ describe('ChromaVector Integration Tests', () => {
901
1090
  } catch {
902
1091
  // Ignore errors if index doesn't exist
903
1092
  }
904
- await vectorDB.createIndex(testIndexName3, dimension);
1093
+ await vectorDB.createIndex({ indexName: testIndexName3, dimension });
905
1094
 
906
1095
  const testVectors = [
907
1096
  [1.0, 0.0, 0.0],
@@ -916,7 +1105,13 @@ describe('ChromaVector Integration Tests', () => {
916
1105
  ];
917
1106
  const testIds = ['doc1', 'doc2', 'doc3'];
918
1107
 
919
- await vectorDB.upsert(testIndexName3, testVectors, testMetadata, testIds, testDocuments);
1108
+ await vectorDB.upsert({
1109
+ indexName: testIndexName3,
1110
+ vectors: testVectors,
1111
+ documents: testDocuments,
1112
+ metadata: testMetadata,
1113
+ ids: testIds,
1114
+ });
920
1115
 
921
1116
  // Wait for indexing
922
1117
  await new Promise(resolve => setTimeout(resolve, 2000));
@@ -933,29 +1128,39 @@ describe('ChromaVector Integration Tests', () => {
933
1128
 
934
1129
  describe('Basic Document Operations', () => {
935
1130
  it('should store and retrieve documents', async () => {
936
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3);
1131
+ const results = await vectorDB.query({ indexName: testIndexName3, queryVector: [1.0, 0.0, 0.0], topK: 3 });
937
1132
  expect(results).toHaveLength(3);
938
1133
  // Verify documents are returned
939
1134
  expect(results[0].document).toBe(testDocuments[0]);
940
1135
  });
941
1136
 
942
1137
  it('should filter documents using $contains', async () => {
943
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
944
- $contains: 'quick',
1138
+ const results = await vectorDB.query({
1139
+ indexName: testIndexName3,
1140
+ queryVector: [1.0, 0.0, 0.0],
1141
+ topK: 3,
1142
+ documentFilter: { $contains: 'quick' },
945
1143
  });
946
1144
  expect(results).toHaveLength(2);
947
1145
  });
948
1146
 
949
1147
  it('should filter with $not_contains', async () => {
950
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
951
- $not_contains: 'fox',
1148
+ const results = await vectorDB.query({
1149
+ indexName: testIndexName3,
1150
+ queryVector: [1.0, 0.0, 0.0],
1151
+ topK: 3,
1152
+ documentFilter: { $not_contains: 'fox' },
952
1153
  });
953
1154
  expect(results.every(r => !r.document?.includes('fox'))).toBe(true);
954
1155
  });
955
1156
 
956
1157
  it('should combine metadata and document filters', async () => {
957
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, { source: 'pangram1' }, false, {
958
- $contains: 'fox',
1158
+ const results = await vectorDB.query({
1159
+ indexName: testIndexName3,
1160
+ queryVector: [1.0, 0.0, 0.0],
1161
+ topK: 3,
1162
+ filter: { source: 'pangram1' },
1163
+ documentFilter: { $contains: 'fox' },
959
1164
  });
960
1165
  expect(results).toHaveLength(1);
961
1166
  expect(results[0].metadata?.source).toBe('pangram1');
@@ -965,8 +1170,11 @@ describe('ChromaVector Integration Tests', () => {
965
1170
 
966
1171
  describe('Complex Document Filtering', () => {
967
1172
  it('should handle $and conditions', async () => {
968
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
969
- $and: [{ $contains: 'quick' }, { $not_contains: 'fox' }],
1173
+ const results = await vectorDB.query({
1174
+ indexName: testIndexName3,
1175
+ queryVector: [1.0, 0.0, 0.0],
1176
+ topK: 3,
1177
+ documentFilter: { $and: [{ $contains: 'quick' }, { $not_contains: 'fox' }] },
970
1178
  });
971
1179
  expect(results).toHaveLength(1);
972
1180
  expect(results[0].document).toContain('quick');
@@ -974,62 +1182,84 @@ describe('ChromaVector Integration Tests', () => {
974
1182
  });
975
1183
 
976
1184
  it('should handle $or conditions', async () => {
977
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
978
- $or: [{ $contains: 'fox' }, { $contains: 'zebras' }],
1185
+ const results = await vectorDB.query({
1186
+ indexName: testIndexName3,
1187
+ queryVector: [1.0, 0.0, 0.0],
1188
+ topK: 3,
1189
+ documentFilter: { $or: [{ $contains: 'fox' }, { $contains: 'zebras' }] },
979
1190
  });
980
1191
  expect(results).toHaveLength(2);
1192
+ expect(results[0].document).toContain('fox');
1193
+ expect(results[1].document).toContain('zebras');
981
1194
  });
982
1195
  });
983
1196
 
984
1197
  describe('Edge Cases and Validation', () => {
985
1198
  it('should reject empty string in $contains', async () => {
986
1199
  await expect(
987
- vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, { $contains: '' }),
1200
+ vectorDB.query({
1201
+ indexName: testIndexName3,
1202
+ queryVector: [1.0, 0.0, 0.0],
1203
+ topK: 3,
1204
+ documentFilter: { $contains: '' },
1205
+ }),
988
1206
  ).rejects.toThrow('Expected where document operand value for operator $contains to be a non-empty str');
989
1207
  });
990
1208
 
991
1209
  it('should be case sensitive', async () => {
992
1210
  // First verify lowercase works
993
- const lowerResults = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
994
- $contains: 'quick',
1211
+ const lowerResults = await vectorDB.query({
1212
+ indexName: testIndexName3,
1213
+ queryVector: [1.0, 0.0, 0.0],
1214
+ topK: 3,
1215
+ documentFilter: { $contains: 'quick' },
995
1216
  });
996
1217
  expect(lowerResults.length).toBe(2);
997
1218
 
998
1219
  // Then verify uppercase doesn't match
999
- const upperResults = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
1000
- $contains: 'QUICK',
1220
+ const upperResults = await vectorDB.query({
1221
+ indexName: testIndexName3,
1222
+ queryVector: [1.0, 0.0, 0.0],
1223
+ topK: 3,
1224
+ documentFilter: { $contains: 'QUICK' },
1001
1225
  });
1002
1226
  expect(upperResults.length).toBe(0);
1003
1227
 
1004
- const upperResults2 = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
1005
- $contains: 'JUMP',
1228
+ const upperResults2 = await vectorDB.query({
1229
+ indexName: testIndexName3,
1230
+ queryVector: [1.0, 0.0, 0.0],
1231
+ topK: 3,
1232
+ documentFilter: { $contains: 'JUMP' },
1006
1233
  });
1007
1234
  expect(upperResults2.length).toBe(1);
1008
1235
  });
1009
1236
 
1010
1237
  it('should handle exact string matches', async () => {
1011
- const results = await vectorDB.query(
1012
- testIndexName3,
1013
- [1.0, 0.0, 0.0],
1014
- 3,
1015
- undefined,
1016
- false,
1017
- { $contains: 'quick brown' }, // Test multi-word match
1018
- );
1238
+ const results = await vectorDB.query({
1239
+ indexName: testIndexName3,
1240
+ queryVector: [1.0, 0.0, 0.0],
1241
+ topK: 3,
1242
+ documentFilter: { $contains: 'quick brown' }, // Test multi-word match
1243
+ });
1019
1244
  expect(results.length).toBe(1);
1020
1245
  expect(results[0].document).toContain('quick brown');
1021
1246
  });
1022
1247
 
1023
1248
  it('should handle deeply nested logical operators', async () => {
1024
- const results = await vectorDB.query(testIndexName3, [1.0, 0.0, 0.0], 3, undefined, false, {
1025
- $or: [
1026
- {
1027
- $and: [{ $contains: 'quick' }, { $not_contains: 'fox' }],
1028
- },
1029
- {
1030
- $and: [{ $contains: 'box' }, { $not_contains: 'quick' }],
1031
- },
1032
- ],
1249
+ const results = await vectorDB.query({
1250
+ indexName: testIndexName3,
1251
+ queryVector: [1.0, 0.0, 0.0],
1252
+ topK: 3,
1253
+ documentFilter: {
1254
+ $or: [
1255
+ {
1256
+ $and: [{ $contains: 'quick' }, { $not_contains: 'fox' }],
1257
+ },
1258
+ {
1259
+ $and: [{ $contains: 'box' }, { $not_contains: 'quick' }],
1260
+ },
1261
+ ],
1262
+ },
1033
1263
  });
1034
1264
  expect(results.length).toBeGreaterThan(0);
1035
1265
  results.forEach(result => {
@@ -1042,4 +1272,113 @@ describe('ChromaVector Integration Tests', () => {
1042
1272
  });
1043
1273
  });
1044
1274
  });
1275
+ describe('Deprecation Warnings', () => {
1276
+ const indexName = 'testdeprecationwarnings';
1277
+
1278
+ const indexName2 = 'testdeprecationwarnings2';
1279
+
1280
+ let warnSpy;
1281
+
1282
+ beforeAll(async () => {
1283
+ await vectorDB.createIndex({ indexName: indexName, dimension: 3 });
1284
+ });
1285
+
1286
+ afterAll(async () => {
1287
+ try {
1288
+ await vectorDB.deleteIndex(indexName);
1289
+ } catch {
1290
+ // Ignore errors if index doesn't exist
1291
+ }
1292
+ try {
1293
+ await vectorDB.deleteIndex(indexName2);
1294
+ } catch {
1295
+ // Ignore errors if index doesn't exist
1296
+ }
1297
+ });
1298
+
1299
+ beforeEach(async () => {
1300
+ warnSpy = vi.spyOn(vectorDB['logger'], 'warn');
1301
+ });
1302
+
1303
+ afterEach(async () => {
1304
+ warnSpy.mockRestore();
1305
+ try {
1306
+ await vectorDB.deleteIndex(indexName2);
1307
+ } catch {
1308
+ // Ignore errors if index doesn't exist
1309
+ }
1310
+ });
1311
+
1312
+ it('should show deprecation warning when using individual args for createIndex', async () => {
1313
+ await vectorDB.createIndex(indexName2, 3, 'cosine');
1314
+
1315
+ expect(warnSpy).toHaveBeenCalledWith(
1316
+ expect.stringContaining('Deprecation Warning: Passing individual arguments to createIndex() is deprecated'),
1317
+ );
1318
+ });
1319
+
1320
+ it('should show deprecation warning when using individual args for upsert', async () => {
1321
+ await vectorDB.upsert(indexName, [[1, 2, 3]], [{ test: 'data' }]);
1322
+
1323
+ expect(warnSpy).toHaveBeenCalledWith(
1324
+ expect.stringContaining('Deprecation Warning: Passing individual arguments to upsert() is deprecated'),
1325
+ );
1326
+ });
1327
+
1328
+ it('should show deprecation warning when using individual args for query', async () => {
1329
+ await vectorDB.query(indexName, [1, 2, 3], 5);
1330
+
1331
+ expect(warnSpy).toHaveBeenCalledWith(
1332
+ expect.stringContaining('Deprecation Warning: Passing individual arguments to query() is deprecated'),
1333
+ );
1334
+ });
1335
+
1336
+ it('should not show deprecation warning when using object param for query', async () => {
1337
+ await vectorDB.query({
1338
+ indexName,
1339
+ queryVector: [1, 2, 3],
1340
+ topK: 5,
1341
+ });
1342
+
1343
+ expect(warnSpy).not.toHaveBeenCalled();
1344
+ });
1345
+
1346
+ it('should not show deprecation warning when using object param for createIndex', async () => {
1347
+ await vectorDB.createIndex({
1348
+ indexName: indexName2,
1349
+ dimension: 3,
1350
+ metric: 'cosine',
1351
+ });
1352
+
1353
+ expect(warnSpy).not.toHaveBeenCalled();
1354
+ });
1355
+
1356
+ it('should not show deprecation warning when using object param for upsert', async () => {
1357
+ await vectorDB.upsert({
1358
+ indexName,
1359
+ vectors: [[1, 2, 3]],
1360
+ metadata: [{ test: 'data' }],
1361
+ });
1362
+
1363
+ expect(warnSpy).not.toHaveBeenCalled();
1364
+ });
1365
+
1366
+ it('should maintain backward compatibility with individual args', async () => {
1367
+ // Query
1368
+ const queryResults = await vectorDB.query(indexName, [1, 2, 3], 5);
1369
+ expect(Array.isArray(queryResults)).toBe(true);
1370
+
1371
+ // CreateIndex
1372
+ await expect(vectorDB.createIndex(indexName2, 3, 'cosine')).resolves.not.toThrow();
1373
+
1374
+ // Upsert
1375
+ const upsertResults = await vectorDB.upsert({
1376
+ indexName,
1377
+ vectors: [[1, 2, 3]],
1378
+ metadata: [{ test: 'data' }],
1379
+ });
1380
+ expect(Array.isArray(upsertResults)).toBe(true);
1381
+ expect(upsertResults).toHaveLength(1);
1382
+ });
1383
+ });
1045
1384
  });