@mastra/opensearch 0.10.3 → 0.10.4-alpha.1

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,6 @@
1
1
  import { beforeEach, describe, expect, it } from 'vitest';
2
2
 
3
+ import type { OpenSearchVectorFilter } from './filter';
3
4
  import { OpenSearchFilterTranslator } from './filter';
4
5
 
5
6
  describe('OpenSearchFilterTranslator', () => {
@@ -13,19 +14,19 @@ describe('OpenSearchFilterTranslator', () => {
13
14
  describe('basic operations', () => {
14
15
  it('handles empty filters', () => {
15
16
  expect(translator.translate({})).toEqual(undefined);
16
- expect(translator.translate(null as any)).toEqual(undefined);
17
- expect(translator.translate(undefined as any)).toEqual(undefined);
17
+ expect(translator.translate(null)).toEqual(undefined);
18
+ expect(translator.translate(undefined)).toEqual(undefined);
18
19
  });
19
20
 
20
21
  it('translates simple field equality to term query', () => {
21
- const filter = { field: 'value' };
22
+ const filter: OpenSearchVectorFilter = { field: 'value' };
22
23
  expect(translator.translate(filter)).toEqual({
23
24
  term: { 'metadata.field.keyword': 'value' },
24
25
  });
25
26
  });
26
27
 
27
28
  it('translates multiple top-level fields to bool must', () => {
28
- const filter = { field1: 'value1', field2: 'value2' };
29
+ const filter: OpenSearchVectorFilter = { field1: 'value1', field2: 'value2' };
29
30
  expect(translator.translate(filter)).toEqual({
30
31
  bool: {
31
32
  must: [{ term: { 'metadata.field1.keyword': 'value1' } }, { term: { 'metadata.field2.keyword': 'value2' } }],
@@ -62,14 +63,14 @@ describe('OpenSearchFilterTranslator', () => {
62
63
  // Comparison Operators
63
64
  describe('comparison operators', () => {
64
65
  it('translates $eq operator', () => {
65
- const filter = { field: { $eq: 'value' } };
66
+ const filter: OpenSearchVectorFilter = { field: { $eq: 'value' } };
66
67
  expect(translator.translate(filter)).toEqual({
67
68
  term: { 'metadata.field.keyword': 'value' },
68
69
  });
69
70
  });
70
71
 
71
72
  it('translates $ne operator', () => {
72
- const filter = { field: { $ne: 'value' } };
73
+ const filter: OpenSearchVectorFilter = { field: { $ne: 'value' } };
73
74
  expect(translator.translate(filter)).toEqual({
74
75
  bool: {
75
76
  must_not: [{ term: { 'metadata.field.keyword': 'value' } }],
@@ -79,7 +80,7 @@ describe('OpenSearchFilterTranslator', () => {
79
80
 
80
81
  it('handles date values', () => {
81
82
  const date = new Date('2024-01-01');
82
- const filter = { timestamp: { $gt: date } };
83
+ const filter: OpenSearchVectorFilter = { timestamp: { $gt: date } };
83
84
  expect(translator.translate(filter)).toEqual({
84
85
  range: { 'metadata.timestamp': { gt: date.toISOString() } },
85
86
  });
@@ -89,7 +90,7 @@ describe('OpenSearchFilterTranslator', () => {
89
90
  // Logical Operators
90
91
  describe('logical operators', () => {
91
92
  it('translates $and operator', () => {
92
- const filter = {
93
+ const filter: OpenSearchVectorFilter = {
93
94
  $and: [{ field1: 'value1' }, { field2: 'value2' }],
94
95
  };
95
96
  expect(translator.translate(filter)).toEqual({
@@ -100,7 +101,7 @@ describe('OpenSearchFilterTranslator', () => {
100
101
  });
101
102
 
102
103
  it('translates $or operator', () => {
103
- const filter = {
104
+ const filter: OpenSearchVectorFilter = {
104
105
  $or: [{ field1: 'value1' }, { field2: 'value2' }],
105
106
  };
106
107
  expect(translator.translate(filter)).toEqual({
@@ -114,7 +115,7 @@ describe('OpenSearchFilterTranslator', () => {
114
115
  });
115
116
 
116
117
  it('translates $not operator', () => {
117
- const filter = {
118
+ const filter: OpenSearchVectorFilter = {
118
119
  $not: { field: 'value' },
119
120
  };
120
121
  expect(translator.translate(filter)).toEqual({
@@ -125,7 +126,7 @@ describe('OpenSearchFilterTranslator', () => {
125
126
  });
126
127
 
127
128
  it('translates $not with $eq operator', () => {
128
- const filter = { field: { $not: { $eq: 'value' } } };
129
+ const filter: OpenSearchVectorFilter = { field: { $not: { $eq: 'value' } } };
129
130
  expect(translator.translate(filter)).toEqual({
130
131
  bool: {
131
132
  must_not: [{ term: { 'metadata.field.keyword': 'value' } }],
@@ -134,7 +135,7 @@ describe('OpenSearchFilterTranslator', () => {
134
135
  });
135
136
 
136
137
  it('translates $not with $ne operator', () => {
137
- const filter = { field: { $not: { $ne: 'value' } } };
138
+ const filter: OpenSearchVectorFilter = { field: { $not: { $ne: 'value' } } };
138
139
  expect(translator.translate(filter)).toEqual({
139
140
  bool: {
140
141
  must_not: [
@@ -149,14 +150,14 @@ describe('OpenSearchFilterTranslator', () => {
149
150
  });
150
151
 
151
152
  it('translates $not with $eq null', () => {
152
- const filter = { field: { $not: { $eq: null } } };
153
+ const filter: OpenSearchVectorFilter = { field: { $not: { $eq: null } } };
153
154
  expect(translator.translate(filter)).toEqual({
154
155
  exists: { field: 'metadata.field' },
155
156
  });
156
157
  });
157
158
 
158
159
  it('translates $not with $ne null', () => {
159
- const filter = { field: { $not: { $ne: null } } };
160
+ const filter: OpenSearchVectorFilter = { field: { $not: { $ne: null } } };
160
161
  expect(translator.translate(filter)).toEqual({
161
162
  bool: {
162
163
  must_not: [{ exists: { field: 'metadata.field' } }],
@@ -165,7 +166,7 @@ describe('OpenSearchFilterTranslator', () => {
165
166
  });
166
167
 
167
168
  it('translates $not with nested fields', () => {
168
- const filter = { 'user.profile.age': { $not: { $gt: 25 } } };
169
+ const filter: OpenSearchVectorFilter = { 'user.profile.age': { $not: { $gt: 25 } } };
169
170
  expect(translator.translate(filter)).toEqual({
170
171
  bool: {
171
172
  must_not: [
@@ -178,7 +179,7 @@ describe('OpenSearchFilterTranslator', () => {
178
179
  });
179
180
 
180
181
  it('translates $not with multiple operators', () => {
181
- const filter = { price: { $not: { $gte: 30, $lte: 70 } } };
182
+ const filter: OpenSearchVectorFilter = { price: { $not: { $gte: 30, $lte: 70 } } };
182
183
  expect(translator.translate(filter)).toEqual({
183
184
  bool: {
184
185
  must_not: [
@@ -191,7 +192,7 @@ describe('OpenSearchFilterTranslator', () => {
191
192
  });
192
193
 
193
194
  it('handles empty $and array', () => {
194
- const filter = {
195
+ const filter: OpenSearchVectorFilter = {
195
196
  $and: [],
196
197
  };
197
198
  // Empty $and should match everything
@@ -199,7 +200,7 @@ describe('OpenSearchFilterTranslator', () => {
199
200
  });
200
201
 
201
202
  it('handles empty $or array', () => {
202
- const filter = {
203
+ const filter: OpenSearchVectorFilter = {
203
204
  $or: [],
204
205
  };
205
206
  // Empty $or should match nothing
@@ -218,7 +219,7 @@ describe('OpenSearchFilterTranslator', () => {
218
219
  });
219
220
 
220
221
  it('handles $not with comparison operators', () => {
221
- const filter = {
222
+ const filter: OpenSearchVectorFilter = {
222
223
  price: { $not: { $gt: 100 } },
223
224
  };
224
225
  expect(translator.translate(filter)).toEqual({
@@ -229,7 +230,7 @@ describe('OpenSearchFilterTranslator', () => {
229
230
  });
230
231
 
231
232
  it('handles nested $not with $or', () => {
232
- const filter = {
233
+ const filter: OpenSearchVectorFilter = {
233
234
  $not: { $or: [{ category: 'electronics' }, { category: 'books' }] },
234
235
  };
235
236
  expect(translator.translate(filter)).toEqual({
@@ -249,7 +250,7 @@ describe('OpenSearchFilterTranslator', () => {
249
250
  });
250
251
 
251
252
  it('handles $not with $not operator', () => {
252
- const filter = {
253
+ const filter: OpenSearchVectorFilter = {
253
254
  $not: { $not: { category: 'electronics' } },
254
255
  };
255
256
  expect(translator.translate(filter)).toEqual({
@@ -266,7 +267,7 @@ describe('OpenSearchFilterTranslator', () => {
266
267
  });
267
268
 
268
269
  it('handles nested logical operators', () => {
269
- const filter = {
270
+ const filter: OpenSearchVectorFilter = {
270
271
  $and: [
271
272
  { field1: 'value1' },
272
273
  {
@@ -295,14 +296,14 @@ describe('OpenSearchFilterTranslator', () => {
295
296
  // Array Operators
296
297
  describe('array operators', () => {
297
298
  it('translates $in operator', () => {
298
- const filter = { field: { $in: ['value1', 'value2'] } };
299
+ const filter: OpenSearchVectorFilter = { field: { $in: ['value1', 'value2'] } };
299
300
  expect(translator.translate(filter)).toEqual({
300
301
  terms: { 'metadata.field.keyword': ['value1', 'value2'] },
301
302
  });
302
303
  });
303
304
 
304
305
  it('translates $nin operator', () => {
305
- const filter = { field: { $nin: ['value1', 'value2'] } };
306
+ const filter: OpenSearchVectorFilter = { field: { $nin: ['value1', 'value2'] } };
306
307
  expect(translator.translate(filter)).toEqual({
307
308
  bool: {
308
309
  must_not: [{ terms: { 'metadata.field.keyword': ['value1', 'value2'] } }],
@@ -311,7 +312,7 @@ describe('OpenSearchFilterTranslator', () => {
311
312
  });
312
313
 
313
314
  it('translates $all operator', () => {
314
- const filter = { field: { $all: ['value1', 'value2'] } };
315
+ const filter: OpenSearchVectorFilter = { field: { $all: ['value1', 'value2'] } };
315
316
  expect(translator.translate(filter)).toEqual({
316
317
  bool: {
317
318
  must: [{ term: { 'metadata.field.keyword': 'value1' } }, { term: { 'metadata.field.keyword': 'value2' } }],
@@ -320,7 +321,7 @@ describe('OpenSearchFilterTranslator', () => {
320
321
  });
321
322
 
322
323
  it('handles empty $in array', () => {
323
- const filter = { field: { $in: [] } };
324
+ const filter: OpenSearchVectorFilter = { field: { $in: [] } };
324
325
  // Empty $in should match nothing (empty terms)
325
326
  expect(translator.translate(filter)).toEqual({
326
327
  terms: { 'metadata.field.keyword': [] },
@@ -328,7 +329,7 @@ describe('OpenSearchFilterTranslator', () => {
328
329
  });
329
330
 
330
331
  it('handles empty $nin array', () => {
331
- const filter = { field: { $nin: [] } };
332
+ const filter: OpenSearchVectorFilter = { field: { $nin: [] } };
332
333
  // Empty $nin should match everything
333
334
  expect(translator.translate(filter)).toEqual({
334
335
  match_all: {},
@@ -336,7 +337,7 @@ describe('OpenSearchFilterTranslator', () => {
336
337
  });
337
338
 
338
339
  it('handles empty $all array', () => {
339
- const filter = { field: { $all: [] } };
340
+ const filter: OpenSearchVectorFilter = { field: { $all: [] } };
340
341
  // Empty $all should match nothing
341
342
  expect(translator.translate(filter)).toEqual({
342
343
  bool: {
@@ -346,7 +347,7 @@ describe('OpenSearchFilterTranslator', () => {
346
347
  });
347
348
 
348
349
  it('handles $not with array operators', () => {
349
- const filter = { tags: { $not: { $in: ['premium', 'new'] } } };
350
+ const filter: OpenSearchVectorFilter = { tags: { $not: { $in: ['premium', 'new'] } } };
350
351
  expect(translator.translate(filter)).toEqual({
351
352
  bool: {
352
353
  must_not: [
@@ -359,7 +360,7 @@ describe('OpenSearchFilterTranslator', () => {
359
360
  });
360
361
 
361
362
  it('handles $not with empty array operators', () => {
362
- const filter = { tags: { $not: { $in: [] } } };
363
+ const filter: OpenSearchVectorFilter = { tags: { $not: { $in: [] } } };
363
364
  expect(translator.translate(filter)).toEqual({
364
365
  bool: {
365
366
  must_not: [
@@ -375,14 +376,14 @@ describe('OpenSearchFilterTranslator', () => {
375
376
  // Element Operators
376
377
  describe('element operators', () => {
377
378
  it('translates $exists operator', () => {
378
- const filter = { field: { $exists: true } };
379
+ const filter: OpenSearchVectorFilter = { field: { $exists: true } };
379
380
  expect(translator.translate(filter)).toEqual({
380
381
  exists: { field: 'metadata.field' },
381
382
  });
382
383
  });
383
384
 
384
385
  it('translates $exists operator with false', () => {
385
- const filter = { field: { $exists: false } };
386
+ const filter: OpenSearchVectorFilter = { field: { $exists: false } };
386
387
  expect(translator.translate(filter)).toEqual({
387
388
  bool: {
388
389
  must_not: [{ exists: { field: 'metadata.field' } }],
@@ -394,14 +395,14 @@ describe('OpenSearchFilterTranslator', () => {
394
395
  // Regex Operators
395
396
  describe('regex operators', () => {
396
397
  it('translates $regex operator', () => {
397
- const filter = { field: { $regex: 'pattern' } };
398
+ const filter: OpenSearchVectorFilter = { field: { $regex: 'pattern' } };
398
399
  expect(translator.translate(filter)).toEqual({
399
400
  regexp: { 'metadata.field': 'pattern' },
400
401
  });
401
402
  });
402
403
 
403
404
  it('handles $regex with start anchor', () => {
404
- const filter = { category: { $regex: '^elect' } };
405
+ const filter: OpenSearchVectorFilter = { category: { $regex: '^elect' } };
405
406
  // Should use wildcard for better anchor handling
406
407
  expect(translator.translate(filter)).toEqual({
407
408
  wildcard: { 'metadata.category': 'elect*' },
@@ -409,7 +410,7 @@ describe('OpenSearchFilterTranslator', () => {
409
410
  });
410
411
 
411
412
  it('handles $regex with end anchor', () => {
412
- const filter = { category: { $regex: 'nics$' } };
413
+ const filter: OpenSearchVectorFilter = { category: { $regex: 'nics$' } };
413
414
  // Should use wildcard for better anchor handling
414
415
  expect(translator.translate(filter)).toEqual({
415
416
  wildcard: { 'metadata.category': '*nics' },
@@ -417,7 +418,7 @@ describe('OpenSearchFilterTranslator', () => {
417
418
  });
418
419
 
419
420
  it('handles $regex with both anchors', () => {
420
- const filter = { category: { $regex: '^electronics$' } };
421
+ const filter: OpenSearchVectorFilter = { category: { $regex: '^electronics$' } };
421
422
  // Should use exact match for both anchors
422
423
  expect(translator.translate(filter)).toEqual({
423
424
  wildcard: { 'metadata.category': 'electronics' },
@@ -425,7 +426,7 @@ describe('OpenSearchFilterTranslator', () => {
425
426
  });
426
427
 
427
428
  it('handles $not with $regex operator', () => {
428
- const filter = { category: { $not: { $regex: '^elect' } } };
429
+ const filter: OpenSearchVectorFilter = { category: { $not: { $regex: '^elect' } } };
429
430
  expect(translator.translate(filter)).toEqual({
430
431
  bool: {
431
432
  must_not: [
@@ -441,14 +442,14 @@ describe('OpenSearchFilterTranslator', () => {
441
442
  // Complex Queries
442
443
  describe('complex queries', () => {
443
444
  it('translates numeric operators', () => {
444
- const filter = { price: { $gt: 70, $lte: 100 } };
445
+ const filter: OpenSearchVectorFilter = { price: { $gt: 70, $lte: 100 } };
445
446
  expect(translator.translate(filter)).toEqual({
446
447
  range: { 'metadata.price': { gt: 70, lte: 100 } },
447
448
  });
448
449
  });
449
450
 
450
451
  it('translates multiple range operators on the same field', () => {
451
- const filter = { price: { $gte: 50, $lt: 200 } };
452
+ const filter: OpenSearchVectorFilter = { price: { $gte: 50, $lt: 200 } };
452
453
  expect(translator.translate(filter)).toEqual({
453
454
  range: { 'metadata.price': { gte: 50, lt: 200 } },
454
455
  });
@@ -456,14 +457,14 @@ describe('OpenSearchFilterTranslator', () => {
456
457
 
457
458
  it('translates all four range operators combined', () => {
458
459
  // This is an edge case that would never occur in practice, but tests the implementation
459
- const filter = { value: { $gt: 10, $gte: 20, $lt: 100, $lte: 90 } };
460
+ const filter: OpenSearchVectorFilter = { value: { $gt: 10, $gte: 20, $lt: 100, $lte: 90 } };
460
461
  expect(translator.translate(filter)).toEqual({
461
462
  range: { 'metadata.value': { gt: 10, gte: 20, lt: 100, lte: 90 } },
462
463
  });
463
464
  });
464
465
 
465
466
  it('translates mixed numeric and non-numeric operators', () => {
466
- const filter = { price: { $gt: 50, $exists: true } };
467
+ const filter: OpenSearchVectorFilter = { price: { $gt: 50, $exists: true } };
467
468
  expect(translator.translate(filter)).toEqual({
468
469
  bool: {
469
470
  must: [{ range: { 'metadata.price': { gt: 50 } } }, { exists: { field: 'metadata.price' } }],
@@ -471,7 +472,7 @@ describe('OpenSearchFilterTranslator', () => {
471
472
  });
472
473
  });
473
474
  it('translates mixed operators', () => {
474
- const filter = {
475
+ const filter: OpenSearchVectorFilter = {
475
476
  $and: [{ field1: { $gt: 10 } }, { field2: { $in: ['value1', 'value2'] } }, { field3: { $exists: true } }],
476
477
  };
477
478
  expect(translator.translate(filter)).toEqual({
@@ -486,7 +487,7 @@ describe('OpenSearchFilterTranslator', () => {
486
487
  });
487
488
 
488
489
  it('translates complex nested queries', () => {
489
- const filter = {
490
+ const filter: OpenSearchVectorFilter = {
490
491
  $and: [
491
492
  { status: 'active' },
492
493
  {
@@ -542,7 +543,7 @@ describe('OpenSearchFilterTranslator', () => {
542
543
 
543
544
  it('throws error for invalid array operator values', () => {
544
545
  const filter = { field: { $in: 'not-an-array' } };
545
- expect(() => translator.translate(filter)).toThrow();
546
+ expect(() => translator.translate(filter as any)).toThrow();
546
547
  });
547
548
 
548
549
  it('throws error for nested invalid operators', () => {
@@ -553,7 +554,7 @@ describe('OpenSearchFilterTranslator', () => {
553
554
 
554
555
  describe('special values', () => {
555
556
  it('handles boolean values', () => {
556
- const filter = { active: true, disabled: false };
557
+ const filter: OpenSearchVectorFilter = { active: true, disabled: false };
557
558
  expect(translator.translate(filter)).toEqual({
558
559
  bool: {
559
560
  must: [{ term: { 'metadata.active': true } }, { term: { 'metadata.disabled': false } }],
@@ -562,7 +563,7 @@ describe('OpenSearchFilterTranslator', () => {
562
563
  });
563
564
 
564
565
  it('handles null values', () => {
565
- const filter = { field: null };
566
+ const filter: OpenSearchVectorFilter = { field: null };
566
567
  expect(translator.translate(filter)).toEqual({
567
568
  term: { 'metadata.field': null },
568
569
  });
@@ -571,21 +572,21 @@ describe('OpenSearchFilterTranslator', () => {
571
572
 
572
573
  describe('array handling', () => {
573
574
  it('translates array values to terms query', () => {
574
- const filter = { tags: ['premium', 'new'] };
575
+ const filter: OpenSearchVectorFilter = { tags: ['premium', 'new'] };
575
576
  expect(translator.translate(filter)).toEqual({
576
577
  terms: { 'metadata.tags.keyword': ['premium', 'new'] },
577
578
  });
578
579
  });
579
580
 
580
581
  it('translates numeric array values to terms query', () => {
581
- const filter = { scores: [90, 95, 100] };
582
+ const filter: OpenSearchVectorFilter = { scores: [90, 95, 100] };
582
583
  expect(translator.translate(filter)).toEqual({
583
584
  terms: { 'metadata.scores': [90, 95, 100] },
584
585
  });
585
586
  });
586
587
 
587
588
  it('translates empty array values to empty terms query', () => {
588
- const filter = { tags: [] };
589
+ const filter: OpenSearchVectorFilter = { tags: [] };
589
590
  expect(translator.translate(filter)).toEqual({
590
591
  terms: { 'metadata.tags.keyword': [] },
591
592
  });
@@ -609,35 +610,35 @@ describe('OpenSearchFilterTranslator', () => {
609
610
 
610
611
  describe('field type handling', () => {
611
612
  it('adds .keyword suffix for string fields', () => {
612
- const filter = { field: 'value' };
613
+ const filter: OpenSearchVectorFilter = { field: 'value' };
613
614
  expect(translator.translate(filter)).toEqual({
614
615
  term: { 'metadata.field.keyword': 'value' },
615
616
  });
616
617
  });
617
618
 
618
619
  it('adds .keyword suffix for string array fields', () => {
619
- const filter = { field: { $in: ['value1', 'value2'] } };
620
+ const filter: OpenSearchVectorFilter = { field: { $in: ['value1', 'value2'] } };
620
621
  expect(translator.translate(filter)).toEqual({
621
622
  terms: { 'metadata.field.keyword': ['value1', 'value2'] },
622
623
  });
623
624
  });
624
625
 
625
626
  it('does not add .keyword suffix for numeric fields', () => {
626
- const filter = { field: 123 };
627
+ const filter: OpenSearchVectorFilter = { field: 123 };
627
628
  expect(translator.translate(filter)).toEqual({
628
629
  term: { 'metadata.field': 123 },
629
630
  });
630
631
  });
631
632
 
632
633
  it('does not add .keyword suffix for numeric array fields', () => {
633
- const filter = { field: { $in: [1, 2, 3] } };
634
+ const filter: OpenSearchVectorFilter = { field: { $in: [1, 2, 3] } };
634
635
  expect(translator.translate(filter)).toEqual({
635
636
  terms: { 'metadata.field': [1, 2, 3] },
636
637
  });
637
638
  });
638
639
 
639
640
  it('handles mixed field types in complex queries', () => {
640
- const filter = {
641
+ const filter: OpenSearchVectorFilter = {
641
642
  $and: [
642
643
  { textField: 'value' },
643
644
  { numericField: 123 },
@@ -1,30 +1,48 @@
1
- import type { FieldCondition, OperatorSupport, QueryOperator, VectorFilter } from '@mastra/core/vector/filter';
1
+ import type {
2
+ BlacklistedRootOperators,
3
+ LogicalOperatorValueMap,
4
+ OperatorSupport,
5
+ OperatorValueMap,
6
+ QueryOperator,
7
+ VectorFilter,
8
+ } from '@mastra/core/vector/filter';
2
9
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
3
10
 
11
+ type OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;
12
+
13
+ type OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
14
+
15
+ type OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';
16
+
17
+ export type OpenSearchVectorFilter = VectorFilter<
18
+ keyof OpenSearchOperatorValueMap,
19
+ OpenSearchOperatorValueMap,
20
+ OpenSearchLogicalOperatorValueMap,
21
+ OpenSearchBlacklisted
22
+ >;
4
23
  /**
5
24
  * Translator for OpenSearch filter queries.
6
25
  * Maintains OpenSearch-compatible syntax while ensuring proper validation
7
26
  * and normalization of values.
8
27
  */
9
- export class OpenSearchFilterTranslator extends BaseFilterTranslator {
28
+ export class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {
10
29
  protected override getSupportedOperators(): OperatorSupport {
11
30
  return {
12
31
  ...BaseFilterTranslator.DEFAULT_OPERATORS,
13
32
  logical: ['$and', '$or', '$not'],
14
33
  array: ['$in', '$nin', '$all'],
15
- element: ['$exists'],
16
34
  regex: ['$regex'],
17
35
  custom: [],
18
36
  };
19
37
  }
20
38
 
21
- translate(filter?: VectorFilter): VectorFilter {
39
+ translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter {
22
40
  if (this.isEmpty(filter)) return undefined;
23
41
  this.validateFilter(filter);
24
42
  return this.translateNode(filter);
25
43
  }
26
44
 
27
- private translateNode(node: VectorFilter | FieldCondition): any {
45
+ private translateNode(node: OpenSearchVectorFilter): any {
28
46
  // Handle primitive values and arrays
29
47
  if (this.isPrimitive(node) || Array.isArray(node)) {
30
48
  return node;
@@ -1,5 +1,5 @@
1
1
  // To setup a Opensearch server, run the docker compose file in the opensearch directory
2
- import type { QueryResult, QueryVectorParams } from '@mastra/core';
2
+ import type { QueryResult } from '@mastra/core';
3
3
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { OpenSearchVector } from './index';
@@ -215,12 +215,11 @@ describe('OpenSearchVector', () => {
215
215
 
216
216
  await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors, metadata: testMetadata });
217
217
 
218
- const queryParams: QueryVectorParams = {
218
+ const results = await vectorDB.query({
219
219
  indexName: testIndexName,
220
220
  queryVector: [1.0, 0.1, 0.1],
221
221
  topK: 3,
222
- };
223
- const results = await vectorDB.query(queryParams);
222
+ });
224
223
 
225
224
  expect(results).toHaveLength(3);
226
225
  expect(results[0]?.score).toBeGreaterThan(0);
@@ -1197,7 +1196,7 @@ describe('OpenSearchVector', () => {
1197
1196
  vectorDB.query({
1198
1197
  indexName,
1199
1198
  queryVector: [1, 0, 0],
1200
- filter: { price: { $invalid: 100 } },
1199
+ filter: { price: { $invalid: 100 } as any },
1201
1200
  }),
1202
1201
  ).rejects.toThrow('Unsupported operator: $invalid');
1203
1202
  });