@mastra/mongodb 0.11.1-alpha.0 → 0.11.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect, beforeEach } from 'vitest';
2
2
 
3
+ import type { MongoDBVectorFilter } from './filter';
3
4
  import { MongoDBFilterTranslator } from './filter';
4
5
 
5
6
  describe('MongoDBFilterTranslator', () => {
@@ -12,12 +13,12 @@ describe('MongoDBFilterTranslator', () => {
12
13
  // Basic Filter Operations
13
14
  describe('basic operations', () => {
14
15
  it('handles simple equality', () => {
15
- const filter = { field: 'value' };
16
+ const filter: MongoDBVectorFilter = { field: 'value' };
16
17
  expect(translator.translate(filter)).toEqual(filter);
17
18
  });
18
19
 
19
20
  it('handles comparison operators', () => {
20
- const filter = {
21
+ const filter: MongoDBVectorFilter = {
21
22
  age: { $gt: 25 },
22
23
  score: { $lte: 100 },
23
24
  };
@@ -25,7 +26,7 @@ describe('MongoDBFilterTranslator', () => {
25
26
  });
26
27
 
27
28
  it('handles valid multiple operators on same field', () => {
28
- const filter = {
29
+ const filter: MongoDBVectorFilter = {
29
30
  price: { $gt: 100, $lt: 200 },
30
31
  quantity: { $gte: 10, $lte: 20 },
31
32
  };
@@ -33,7 +34,7 @@ describe('MongoDBFilterTranslator', () => {
33
34
  });
34
35
 
35
36
  it('handles null values correctly', () => {
36
- const filter = {
37
+ const filter: MongoDBVectorFilter = {
37
38
  field: null,
38
39
  other: { $eq: null },
39
40
  };
@@ -41,7 +42,7 @@ describe('MongoDBFilterTranslator', () => {
41
42
  });
42
43
 
43
44
  it('handles boolean values correctly', () => {
44
- const filter = {
45
+ const filter: MongoDBVectorFilter = {
45
46
  active: true,
46
47
  deleted: false,
47
48
  status: { $eq: true },
@@ -53,7 +54,7 @@ describe('MongoDBFilterTranslator', () => {
53
54
  // Array Operations
54
55
  describe('array operations', () => {
55
56
  it('handles array operators', () => {
56
- const filter = {
57
+ const filter: MongoDBVectorFilter = {
57
58
  tags: { $all: ['tag1', 'tag2'] },
58
59
  categories: { $in: ['A', 'B'] },
59
60
  items: { $nin: ['item1', 'item2'] },
@@ -63,7 +64,7 @@ describe('MongoDBFilterTranslator', () => {
63
64
  });
64
65
 
65
66
  it('handles empty array values', () => {
66
- const filter = {
67
+ const filter: MongoDBVectorFilter = {
67
68
  tags: { $in: [] },
68
69
  categories: { $all: [] },
69
70
  };
@@ -71,14 +72,14 @@ describe('MongoDBFilterTranslator', () => {
71
72
  });
72
73
 
73
74
  it('handles nested array operators', () => {
74
- const filter = {
75
+ const filter: MongoDBVectorFilter = {
75
76
  $and: [{ tags: { $all: ['tag1', 'tag2'] } }, { 'nested.array': { $in: [1, 2, 3] } }],
76
77
  };
77
78
  expect(translator.translate(filter)).toEqual(filter);
78
79
  });
79
80
 
80
81
  it('handles $size operator', () => {
81
- const filter = {
82
+ const filter: MongoDBVectorFilter = {
82
83
  tags: { $size: 3 },
83
84
  };
84
85
  expect(translator.translate(filter)).toEqual(filter);
@@ -88,14 +89,14 @@ describe('MongoDBFilterTranslator', () => {
88
89
  // Logical Operators
89
90
  describe('logical operators', () => {
90
91
  it('handles logical operators', () => {
91
- const filter = {
92
+ const filter: MongoDBVectorFilter = {
92
93
  $or: [{ status: 'active' }, { age: { $gt: 25 } }],
93
94
  };
94
95
  expect(translator.translate(filter)).toEqual(filter);
95
96
  });
96
97
 
97
98
  it('handles $not operator', () => {
98
- const filter = {
99
+ const filter: MongoDBVectorFilter = {
99
100
  field: { $not: { $eq: 'value' } },
100
101
  $not: { field: 'value' },
101
102
  };
@@ -103,14 +104,14 @@ describe('MongoDBFilterTranslator', () => {
103
104
  });
104
105
 
105
106
  it('handles $nor operator', () => {
106
- const filter = {
107
+ const filter: MongoDBVectorFilter = {
107
108
  $nor: [{ status: 'deleted' }, { active: false }],
108
109
  };
109
110
  expect(translator.translate(filter)).toEqual(filter);
110
111
  });
111
112
 
112
113
  it('handles nested logical operators', () => {
113
- const filter = {
114
+ const filter: MongoDBVectorFilter = {
114
115
  $and: [
115
116
  { status: 'active' },
116
117
  { $or: [{ category: { $in: ['A', 'B'] } }, { $and: [{ price: { $gt: 100 } }, { stock: { $lt: 50 } }] }] },
@@ -120,7 +121,7 @@ describe('MongoDBFilterTranslator', () => {
120
121
  });
121
122
 
122
123
  it('handles empty conditions in logical operators', () => {
123
- const filter = {
124
+ const filter: MongoDBVectorFilter = {
124
125
  $and: [],
125
126
  $or: [{}],
126
127
  field: 'value',
@@ -175,7 +176,7 @@ describe('MongoDBFilterTranslator', () => {
175
176
  expect(() =>
176
177
  translator.translate({
177
178
  $or: [{ $in: ['value1', 'value2'] }],
178
- }),
179
+ } as any),
179
180
  ).toThrow(/Logical operators must contain field conditions/);
180
181
  });
181
182
 
@@ -187,7 +188,7 @@ describe('MongoDBFilterTranslator', () => {
187
188
  $or: [{ subfield: 'value1' }, { subfield: 'value2' }],
188
189
  },
189
190
  },
190
- }),
191
+ } as any),
191
192
  ).toThrow();
192
193
 
193
194
  expect(() =>
@@ -196,7 +197,7 @@ describe('MongoDBFilterTranslator', () => {
196
197
  $in: [
197
198
  {
198
199
  $and: [{ subfield: 'value1' }, { subfield: 'value2' }],
199
- },
200
+ } as any,
200
201
  ],
201
202
  },
202
203
  }),
@@ -211,7 +212,7 @@ describe('MongoDBFilterTranslator', () => {
211
212
  $or: [{ subfield: 'value1' }, { subfield: 'value2' }],
212
213
  },
213
214
  },
214
- }),
215
+ } as any),
215
216
  ).toThrow();
216
217
 
217
218
  expect(() =>
@@ -227,7 +228,7 @@ describe('MongoDBFilterTranslator', () => {
227
228
 
228
229
  it('throws error for $not if not an object', () => {
229
230
  expect(() => translator.translate({ $not: 'value' })).toThrow();
230
- expect(() => translator.translate({ $not: [{ field: 'value' }] })).toThrow();
231
+ expect(() => translator.translate({ $not: [{ field: 'value' }] } as any)).toThrow();
231
232
  });
232
233
 
233
234
  it('throws error for $not if empty', () => {
@@ -238,7 +239,7 @@ describe('MongoDBFilterTranslator', () => {
238
239
  // Nested Objects and Fields
239
240
  describe('nested objects and fields', () => {
240
241
  it('handles nested objects', () => {
241
- const filter = {
242
+ const filter: MongoDBVectorFilter = {
242
243
  'user.profile.age': { $gt: 25 },
243
244
  'user.status': 'active',
244
245
  };
@@ -246,7 +247,7 @@ describe('MongoDBFilterTranslator', () => {
246
247
  });
247
248
 
248
249
  it('handles deeply nested field paths', () => {
249
- const filter = {
250
+ const filter: MongoDBVectorFilter = {
250
251
  'user.profile.address.city': { $eq: 'New York' },
251
252
  'deep.nested.field': { $gt: 100 },
252
253
  };
@@ -295,13 +296,13 @@ describe('MongoDBFilterTranslator', () => {
295
296
  describe('special cases', () => {
296
297
  it('handles empty filters', () => {
297
298
  expect(translator.translate({})).toEqual({});
298
- expect(translator.translate(null as any)).toEqual(null);
299
- expect(translator.translate(undefined as any)).toEqual(undefined);
299
+ expect(translator.translate(null)).toEqual(null);
300
+ expect(translator.translate(undefined)).toEqual(undefined);
300
301
  });
301
302
 
302
303
  it('normalizes dates', () => {
303
304
  const date = new Date('2024-01-01');
304
- const filter = { timestamp: { $gt: date } };
305
+ const filter: MongoDBVectorFilter = { timestamp: { $gt: date } };
305
306
  expect(translator.translate(filter)).toEqual({
306
307
  timestamp: { $gt: date.toISOString() },
307
308
  });
@@ -321,14 +322,14 @@ describe('MongoDBFilterTranslator', () => {
321
322
  // Regex Support
322
323
  describe('regex support', () => {
323
324
  it('handles $regex operator', () => {
324
- const filter = {
325
+ const filter: MongoDBVectorFilter = {
325
326
  name: { $regex: '^test' },
326
327
  };
327
328
  expect(translator.translate(filter)).toEqual(filter);
328
329
  });
329
330
 
330
331
  it('handles RegExp objects', () => {
331
- const filter = {
332
+ const filter: MongoDBVectorFilter = {
332
333
  name: /^test/i,
333
334
  };
334
335
  // RegExp objects should be preserved
@@ -338,7 +339,7 @@ describe('MongoDBFilterTranslator', () => {
338
339
 
339
340
  describe('operator validation', () => {
340
341
  it('ensures all supported operator filters are accepted', () => {
341
- const supportedFilters = [
342
+ const supportedFilters: MongoDBVectorFilter[] = [
342
343
  // Basic comparison operators
343
344
  { field: { $eq: 'value' } },
344
345
  { field: { $ne: 'value' } },
@@ -382,12 +383,21 @@ describe('MongoDBFilterTranslator', () => {
382
383
  });
383
384
 
384
385
  it('throws on unsupported operators', () => {
385
- expect(() => translator.translate({ field: { $unknown: 'value' } })).toThrow('Unsupported operator: $unknown');
386
- expect(() => translator.translate({ $unknown: [{ field: 'value' }] })).toThrow('Unsupported operator: $unknown');
386
+ expect(() => translator.translate({ field: { $unknown: 'value' } } as any)).toThrow(
387
+ 'Unsupported operator: $unknown',
388
+ );
389
+ expect(() => translator.translate({ $unknown: [{ field: 'value' }] } as any)).toThrow(
390
+ 'Unsupported operator: $unknown',
391
+ );
387
392
  });
388
393
 
389
394
  it('throws error for non-logical operators at top level', () => {
390
- const invalidFilters = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $exists: true }, { $regex: 'pattern' }];
395
+ const invalidFilters: any = [
396
+ { $gt: 100 },
397
+ { $in: ['value1', 'value2'] },
398
+ { $exists: true },
399
+ { $regex: 'pattern' },
400
+ ];
391
401
 
392
402
  invalidFilters.forEach(filter => {
393
403
  expect(() => translator.translate(filter)).toThrow(/Invalid top-level operator/);
@@ -1,12 +1,33 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
2
- import type { FieldCondition, VectorFilter, OperatorSupport, QueryOperator } from '@mastra/core/vector/filter';
2
+ import type {
3
+ VectorFilter,
4
+ OperatorSupport,
5
+ QueryOperator,
6
+ OperatorValueMap,
7
+ LogicalOperatorValueMap,
8
+ BlacklistedRootOperators,
9
+ VectorFieldValue,
10
+ } from '@mastra/core/vector/filter';
11
+
12
+ type MongoDBOperatorValueMap = Omit<OperatorValueMap, '$options'> & {
13
+ $size: number;
14
+ };
15
+ type MongoDBBlacklisted = BlacklistedRootOperators | '$size';
16
+
17
+ export type MongoDBVectorFilter = VectorFilter<
18
+ keyof MongoDBOperatorValueMap,
19
+ MongoDBOperatorValueMap,
20
+ LogicalOperatorValueMap,
21
+ MongoDBBlacklisted,
22
+ VectorFieldValue | RegExp
23
+ >;
3
24
 
4
25
  /**
5
26
  * Translator for MongoDB filter queries.
6
27
  * Maintains MongoDB-compatible syntax while ensuring proper validation
7
28
  * and normalization of values.
8
29
  */
9
- export class MongoDBFilterTranslator extends BaseFilterTranslator {
30
+ export class MongoDBFilterTranslator extends BaseFilterTranslator<MongoDBVectorFilter> {
10
31
  protected override getSupportedOperators(): OperatorSupport {
11
32
  return {
12
33
  ...BaseFilterTranslator.DEFAULT_OPERATORS,
@@ -15,14 +36,14 @@ export class MongoDBFilterTranslator extends BaseFilterTranslator {
15
36
  };
16
37
  }
17
38
 
18
- translate(filter?: VectorFilter): any {
39
+ translate(filter?: MongoDBVectorFilter): any {
19
40
  if (this.isEmpty(filter)) return filter;
20
41
  this.validateFilter(filter);
21
42
 
22
43
  return this.translateNode(filter);
23
44
  }
24
45
 
25
- private translateNode(node: VectorFilter | FieldCondition): any {
46
+ private translateNode(node: MongoDBVectorFilter): any {
26
47
  // Handle primitive values and arrays
27
48
  if (this.isRegex(node)) {
28
49
  return node; // Return regex values as-is
@@ -1,4 +1,3 @@
1
- import type { VectorFilter } from '@mastra/core/vector/filter';
2
1
  import { vi, describe, it, expect, beforeAll, afterAll, test } from 'vitest';
3
2
  import { MongoDBVector } from './';
4
3
 
@@ -329,7 +328,7 @@ describe('MongoDBVector Integration Tests', () => {
329
328
  const results = await retryQuery({
330
329
  indexName: testIndexName2,
331
330
  queryVector: [1, 0, 0, 0],
332
- filter: null as unknown as VectorFilter,
331
+ filter: null,
333
332
  });
334
333
  const results2 = await retryQuery({
335
334
  indexName: testIndexName2,