@mastra/astra 0.11.4 → 0.11.7-alpha.0
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 +27 -0
- package/package.json +19 -6
- package/.turbo/turbo-build.log +0 -4
- package/eslint.config.js +0 -6
- package/src/index.ts +0 -2
- package/src/vector/filter.test.ts +0 -353
- package/src/vector/filter.ts +0 -83
- package/src/vector/index.test.ts +0 -1278
- package/src/vector/index.ts +0 -324
- package/src/vector/prompt.ts +0 -91
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -17
- package/vitest.config.ts +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @mastra/astra
|
|
2
2
|
|
|
3
|
+
## 0.11.7-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#7343](https://github.com/mastra-ai/mastra/pull/7343) [`de3cbc6`](https://github.com/mastra-ai/mastra/commit/de3cbc61079211431bd30487982ea3653517278e) Thanks [@LekoArts](https://github.com/LekoArts)! - Update the `package.json` file to include additional fields like `repository`, `homepage` or `files`.
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`85ef90b`](https://github.com/mastra-ai/mastra/commit/85ef90bb2cd4ae4df855c7ac175f7d392c55c1bf), [`de3cbc6`](https://github.com/mastra-ai/mastra/commit/de3cbc61079211431bd30487982ea3653517278e)]:
|
|
10
|
+
- @mastra/core@0.15.3-alpha.5
|
|
11
|
+
|
|
12
|
+
## 0.11.6
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`c6113ed`](https://github.com/mastra-ai/mastra/commit/c6113ed7f9df297e130d94436ceee310273d6430) Thanks [@wardpeet](https://github.com/wardpeet)! - Fix peerdpes for @mastra/core
|
|
17
|
+
|
|
18
|
+
- Updated dependencies []:
|
|
19
|
+
- @mastra/core@0.15.2
|
|
20
|
+
|
|
21
|
+
## 0.11.5
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [`95b2aa9`](https://github.com/mastra-ai/mastra/commit/95b2aa908230919e67efcac0d69005a2d5745298) Thanks [@wardpeet](https://github.com/wardpeet)! - Fix peerdeps @mastra/core
|
|
26
|
+
|
|
27
|
+
- Updated dependencies []:
|
|
28
|
+
- @mastra/core@0.15.1
|
|
29
|
+
|
|
3
30
|
## 0.11.4
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/astra",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.7-alpha.0",
|
|
4
4
|
"description": "Astra DB provider for Mastra - includes vector store capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"CHANGELOG.md"
|
|
11
|
+
],
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"import": {
|
|
@@ -18,7 +22,7 @@
|
|
|
18
22
|
},
|
|
19
23
|
"./package.json": "./package.json"
|
|
20
24
|
},
|
|
21
|
-
"license": "
|
|
25
|
+
"license": "Apache-2.0",
|
|
22
26
|
"dependencies": {
|
|
23
27
|
"@datastax/astra-db-ts": "^1.5.0"
|
|
24
28
|
},
|
|
@@ -29,12 +33,21 @@
|
|
|
29
33
|
"tsup": "^8.5.0",
|
|
30
34
|
"typescript": "^5.8.3",
|
|
31
35
|
"vitest": "^3.2.4",
|
|
32
|
-
"@internal/lint": "0.0.
|
|
33
|
-
"@mastra/core": "0.
|
|
34
|
-
"@internal/types-builder": "0.0.
|
|
36
|
+
"@internal/lint": "0.0.34",
|
|
37
|
+
"@mastra/core": "0.15.3-alpha.5",
|
|
38
|
+
"@internal/types-builder": "0.0.9"
|
|
35
39
|
},
|
|
36
40
|
"peerDependencies": {
|
|
37
|
-
"@mastra/core": ">=0.10.7-0 <0.
|
|
41
|
+
"@mastra/core": ">=0.10.7-0 <0.16.0-0"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://mastra.ai",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/mastra-ai/mastra.git",
|
|
47
|
+
"directory": "stores/astra"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/mastra-ai/mastra/issues"
|
|
38
51
|
},
|
|
39
52
|
"scripts": {
|
|
40
53
|
"build": "tsup --silent --config tsup.config.ts",
|
package/.turbo/turbo-build.log
DELETED
package/eslint.config.js
DELETED
package/src/index.ts
DELETED
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import type { AstraVectorFilter } from './filter';
|
|
4
|
-
import { AstraFilterTranslator } from './filter';
|
|
5
|
-
|
|
6
|
-
describe('AstraFilterTranslator', () => {
|
|
7
|
-
let translator: AstraFilterTranslator;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
translator = new AstraFilterTranslator();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// Basic Filter Operations
|
|
14
|
-
describe('basic operations', () => {
|
|
15
|
-
it('handles simple equality', () => {
|
|
16
|
-
const filter: AstraVectorFilter = { field: 'value' };
|
|
17
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('handles comparison operators', () => {
|
|
21
|
-
const filter: AstraVectorFilter = {
|
|
22
|
-
age: { $gt: 25 },
|
|
23
|
-
score: { $lte: 100 },
|
|
24
|
-
};
|
|
25
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('handles valid multiple operators on same field', () => {
|
|
29
|
-
const filter: AstraVectorFilter = {
|
|
30
|
-
price: { $gt: 100, $lt: 200 },
|
|
31
|
-
quantity: { $gte: 10, $lte: 20 },
|
|
32
|
-
};
|
|
33
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('handles null values correctly', () => {
|
|
37
|
-
const filter: AstraVectorFilter = {
|
|
38
|
-
field: null,
|
|
39
|
-
other: { $eq: null },
|
|
40
|
-
};
|
|
41
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('throws on unsupported combinations', () => {
|
|
45
|
-
const filter: AstraVectorFilter = {
|
|
46
|
-
field: { $gt: 100, $lt: 200 },
|
|
47
|
-
};
|
|
48
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Array Operations
|
|
53
|
-
describe('array operations', () => {
|
|
54
|
-
it('handles array operators', () => {
|
|
55
|
-
const filter: AstraVectorFilter = {
|
|
56
|
-
tags: { $all: ['tag1', 'tag2'] },
|
|
57
|
-
categories: { $in: ['A', 'B'] },
|
|
58
|
-
};
|
|
59
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
60
|
-
});
|
|
61
|
-
it('handles empty array values', () => {
|
|
62
|
-
const filter: AstraVectorFilter = {
|
|
63
|
-
tags: { $in: [] },
|
|
64
|
-
categories: { $all: [] },
|
|
65
|
-
};
|
|
66
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('handles nested array operators', () => {
|
|
70
|
-
const filter: AstraVectorFilter = {
|
|
71
|
-
$and: [{ tags: { $all: ['tag1', 'tag2'] } }, { 'nested.array': { $in: [1, 2, 3] } }],
|
|
72
|
-
};
|
|
73
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Logical Operators
|
|
78
|
-
describe('logical operators', () => {
|
|
79
|
-
it('handles logical operators', () => {
|
|
80
|
-
const filter: AstraVectorFilter = {
|
|
81
|
-
$or: [{ status: 'active' }, { age: { $gt: 25 } }],
|
|
82
|
-
};
|
|
83
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('handles nested logical operators', () => {
|
|
87
|
-
const filter: AstraVectorFilter = {
|
|
88
|
-
$and: [
|
|
89
|
-
{ status: 'active' },
|
|
90
|
-
{ $or: [{ category: { $in: ['A', 'B'] } }, { $and: [{ price: { $gt: 100 } }, { stock: { $lt: 50 } }] }] },
|
|
91
|
-
],
|
|
92
|
-
};
|
|
93
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('handles empty conditions in logical operators', () => {
|
|
97
|
-
const filter: AstraVectorFilter = {
|
|
98
|
-
$and: [],
|
|
99
|
-
$or: [{}],
|
|
100
|
-
field: 'value',
|
|
101
|
-
};
|
|
102
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('allows multiple logical operators at root level with complex conditions', () => {
|
|
106
|
-
expect(() =>
|
|
107
|
-
translator.translate({
|
|
108
|
-
$and: [{ field1: { $gt: 10 } }],
|
|
109
|
-
$or: [{ field2: { $lt: 20 } }],
|
|
110
|
-
field4: { $not: { $eq: 'value' } },
|
|
111
|
-
}),
|
|
112
|
-
).not.toThrow();
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('allows logical operators at root level', () => {
|
|
116
|
-
expect(() =>
|
|
117
|
-
translator.translate({
|
|
118
|
-
$and: [{ field1: 'value1' }, { field2: 'value2' }],
|
|
119
|
-
$or: [{ field3: 'value3' }, { field4: 'value4' }],
|
|
120
|
-
}),
|
|
121
|
-
).not.toThrow();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('allows logical operators nested within other logical operators', () => {
|
|
125
|
-
expect(() =>
|
|
126
|
-
translator.translate({
|
|
127
|
-
$and: [
|
|
128
|
-
{
|
|
129
|
-
$or: [{ field1: 'value1' }, { field2: 'value2' }],
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
$and: [{ field3: 'value3' }, { field4: 'value4' }],
|
|
133
|
-
},
|
|
134
|
-
],
|
|
135
|
-
}),
|
|
136
|
-
).not.toThrow();
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// Logical Operator Validation
|
|
141
|
-
describe('logical operator validation', () => {
|
|
142
|
-
it('throws error for direct operators in logical operator arrays', () => {
|
|
143
|
-
expect(() =>
|
|
144
|
-
translator.translate({
|
|
145
|
-
$and: [{ $eq: 'value' }, { $gt: 100 }],
|
|
146
|
-
}),
|
|
147
|
-
).toThrow(/Logical operators must contain field conditions/);
|
|
148
|
-
|
|
149
|
-
expect(() =>
|
|
150
|
-
translator.translate({
|
|
151
|
-
$or: [{ $in: ['value1', 'value2'] as any }],
|
|
152
|
-
}),
|
|
153
|
-
).toThrow(/Logical operators must contain field conditions/);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('throws error for deeply nested logical operators in non-logical contexts', () => {
|
|
157
|
-
expect(() =>
|
|
158
|
-
translator.translate({
|
|
159
|
-
field: {
|
|
160
|
-
$gt: {
|
|
161
|
-
$or: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
162
|
-
} as any,
|
|
163
|
-
},
|
|
164
|
-
}),
|
|
165
|
-
).toThrow();
|
|
166
|
-
|
|
167
|
-
expect(() =>
|
|
168
|
-
translator.translate({
|
|
169
|
-
field: {
|
|
170
|
-
$in: [
|
|
171
|
-
{
|
|
172
|
-
$and: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
173
|
-
} as any,
|
|
174
|
-
],
|
|
175
|
-
},
|
|
176
|
-
}),
|
|
177
|
-
).toThrow();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('throws error for logical operators nested in non-logical contexts', () => {
|
|
181
|
-
expect(() =>
|
|
182
|
-
translator.translate({
|
|
183
|
-
field: {
|
|
184
|
-
$gt: {
|
|
185
|
-
$or: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
186
|
-
} as any,
|
|
187
|
-
},
|
|
188
|
-
}),
|
|
189
|
-
).toThrow();
|
|
190
|
-
|
|
191
|
-
expect(() =>
|
|
192
|
-
translator.translate({
|
|
193
|
-
field: {
|
|
194
|
-
$not: {
|
|
195
|
-
$and: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
}),
|
|
199
|
-
).not.toThrow(); // $not is allowed to contain logical operators
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('throws error for $not if not an object', () => {
|
|
203
|
-
expect(() => translator.translate({ $not: 'value' })).toThrow();
|
|
204
|
-
expect(() => translator.translate({ $not: [{ field: 'value' }] } as any)).toThrow();
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('throws error for $not if empty', () => {
|
|
208
|
-
expect(() => translator.translate({ $not: {} })).toThrow();
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Nested Objects and Fields
|
|
213
|
-
describe('nested objects and fields', () => {
|
|
214
|
-
it('handles nested objects', () => {
|
|
215
|
-
const filter: AstraVectorFilter = {
|
|
216
|
-
'user.profile.age': { $gt: 25 },
|
|
217
|
-
'user.status': 'active',
|
|
218
|
-
};
|
|
219
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('handles deeply nested field paths', () => {
|
|
223
|
-
const filter: AstraVectorFilter = {
|
|
224
|
-
'user.profile.address.city': { $eq: 'New York' },
|
|
225
|
-
'deep.nested.field': { $gt: 100 },
|
|
226
|
-
};
|
|
227
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it('preserves nested empty objects', () => {
|
|
231
|
-
const filter: AstraVectorFilter = {
|
|
232
|
-
status: 'active',
|
|
233
|
-
metadata: {},
|
|
234
|
-
'user.profile': {},
|
|
235
|
-
'usersettings.theme': null,
|
|
236
|
-
};
|
|
237
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
it('handles mix of operators and empty objects', () => {
|
|
241
|
-
const filter: AstraVectorFilter = {
|
|
242
|
-
tags: { $in: ['a', 'b'] },
|
|
243
|
-
metadata: {},
|
|
244
|
-
'nested.field': { $eq: 'value' },
|
|
245
|
-
'nested.empty': {},
|
|
246
|
-
};
|
|
247
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('handles deeply nested operators', () => {
|
|
251
|
-
const filter: AstraVectorFilter = {
|
|
252
|
-
'user.profile.preferences.theme': { $in: ['dark', 'light'] },
|
|
253
|
-
};
|
|
254
|
-
expect(translator.translate(filter)).toEqual(filter);
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// Special Cases
|
|
259
|
-
describe('special cases', () => {
|
|
260
|
-
it('handles empty filters', () => {
|
|
261
|
-
expect(translator.translate({})).toEqual({});
|
|
262
|
-
expect(translator.translate(null)).toEqual(null);
|
|
263
|
-
expect(translator.translate(undefined)).toEqual(undefined);
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('normalizes dates', () => {
|
|
267
|
-
const date = new Date('2024-01-01');
|
|
268
|
-
const filter: AstraVectorFilter = { timestamp: { $gt: date } };
|
|
269
|
-
expect(translator.translate(filter)).toEqual({
|
|
270
|
-
timestamp: { $gt: date.toISOString() },
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it('allows $not in field-level conditions', () => {
|
|
275
|
-
expect(() =>
|
|
276
|
-
translator.translate({
|
|
277
|
-
field1: { $not: { $eq: 'value1' } },
|
|
278
|
-
field2: { $not: { $in: ['value2', 'value3'] } },
|
|
279
|
-
field3: { $not: { $regex: 'pattern' } },
|
|
280
|
-
}),
|
|
281
|
-
).not.toThrow();
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
describe('operator validation', () => {
|
|
286
|
-
it('ensure all operator filters are supported', () => {
|
|
287
|
-
const supportedFilters: AstraVectorFilter[] = [
|
|
288
|
-
// Basic comparison operators
|
|
289
|
-
{ field: { $eq: 'value' } },
|
|
290
|
-
{ field: { $ne: 'value' } },
|
|
291
|
-
{ field: { $gt: 'value' } },
|
|
292
|
-
{ field: { $gte: 'value' } },
|
|
293
|
-
{ field: { $lt: 'value' } },
|
|
294
|
-
{ field: { $lte: 'value' } },
|
|
295
|
-
|
|
296
|
-
// Array operators
|
|
297
|
-
{ field: { $in: ['value'] } },
|
|
298
|
-
{ field: { $nin: ['value'] } },
|
|
299
|
-
{ field: { $all: ['value'] } },
|
|
300
|
-
|
|
301
|
-
// Existence
|
|
302
|
-
{ field: { $exists: true } },
|
|
303
|
-
|
|
304
|
-
{ $and: [{ field1: 'value1' }, { field2: 'value2' }] },
|
|
305
|
-
{ $or: [{ field1: 'value1' }, { field2: 'value2' }] },
|
|
306
|
-
|
|
307
|
-
{ $not: { field: 'value' } },
|
|
308
|
-
|
|
309
|
-
{ $or: [{ $and: [{ field1: 'value1' }] }, { $not: { field2: 'value2' } }] },
|
|
310
|
-
|
|
311
|
-
{ field: { $not: { $eq: 'value' } } },
|
|
312
|
-
{ field: { $not: { $in: ['value1', 'value2'] } } },
|
|
313
|
-
{ field: { $not: { $gt: 100 } } },
|
|
314
|
-
{ field: { $not: { $lt: 50 } } },
|
|
315
|
-
|
|
316
|
-
{ field: { $size: 1 } },
|
|
317
|
-
];
|
|
318
|
-
|
|
319
|
-
supportedFilters.forEach(filter => {
|
|
320
|
-
expect(() => translator.translate(filter)).not.toThrow();
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('throws on unsupported operators', () => {
|
|
325
|
-
expect(() => translator.translate({ field: { $regex: 'value' } as any })).toThrow('Unsupported operator: $regex');
|
|
326
|
-
const filter: any = { field: /pattern/i };
|
|
327
|
-
expect(() => translator.translate(filter)).toThrow();
|
|
328
|
-
expect(() => translator.translate({ $nor: [{ field: 'value' }] } as any)).toThrow('Unsupported operator: $nor');
|
|
329
|
-
expect(() => translator.translate({ field: { $elemMatch: { $gt: 5 } } } as any)).toThrow(
|
|
330
|
-
'Unsupported operator: $elemMatch',
|
|
331
|
-
);
|
|
332
|
-
});
|
|
333
|
-
it('throws error for non-logical operators at top level', () => {
|
|
334
|
-
const invalidFilters: any = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $exists: true }];
|
|
335
|
-
|
|
336
|
-
invalidFilters.forEach(filter => {
|
|
337
|
-
expect(() => translator.translate(filter)).toThrow(/Invalid top-level operator/);
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
it('allows logical operators at top level', () => {
|
|
342
|
-
const validFilters: AstraVectorFilter[] = [
|
|
343
|
-
{ $and: [{ field: 'value' }] },
|
|
344
|
-
{ $or: [{ field: 'value' }] },
|
|
345
|
-
{ $not: { field: 'value' } },
|
|
346
|
-
];
|
|
347
|
-
|
|
348
|
-
validFilters.forEach(filter => {
|
|
349
|
-
expect(() => translator.translate(filter)).not.toThrow();
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
});
|
package/src/vector/filter.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
2
|
-
import type {
|
|
3
|
-
VectorFilter,
|
|
4
|
-
OperatorSupport,
|
|
5
|
-
QueryOperator,
|
|
6
|
-
OperatorValueMap,
|
|
7
|
-
LogicalOperatorValueMap,
|
|
8
|
-
BlacklistedRootOperators,
|
|
9
|
-
} from '@mastra/core/vector/filter';
|
|
10
|
-
|
|
11
|
-
type AstraOperatorValueMap = Omit<OperatorValueMap, '$elemMatch' | '$regex' | '$options'> & {
|
|
12
|
-
$size: number; // Astra-specific
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
type AstraLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
|
|
16
|
-
|
|
17
|
-
type AstraBlacklisted = BlacklistedRootOperators | '$nor' | '$size';
|
|
18
|
-
|
|
19
|
-
export type AstraVectorFilter = VectorFilter<
|
|
20
|
-
keyof AstraOperatorValueMap,
|
|
21
|
-
AstraOperatorValueMap,
|
|
22
|
-
AstraLogicalOperatorValueMap,
|
|
23
|
-
AstraBlacklisted
|
|
24
|
-
>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Translator for Astra DB filter queries.
|
|
28
|
-
* Maintains MongoDB-compatible syntax while ensuring proper validation
|
|
29
|
-
* and normalization of values.
|
|
30
|
-
*/
|
|
31
|
-
export class AstraFilterTranslator extends BaseFilterTranslator<AstraVectorFilter> {
|
|
32
|
-
protected override getSupportedOperators(): OperatorSupport {
|
|
33
|
-
return {
|
|
34
|
-
...BaseFilterTranslator.DEFAULT_OPERATORS,
|
|
35
|
-
array: ['$all', '$in', '$nin'],
|
|
36
|
-
logical: ['$and', '$or', '$not'],
|
|
37
|
-
regex: [],
|
|
38
|
-
custom: ['$size'],
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
translate(filter?: AstraVectorFilter): AstraVectorFilter {
|
|
43
|
-
if (this.isEmpty(filter)) return filter;
|
|
44
|
-
this.validateFilter(filter);
|
|
45
|
-
|
|
46
|
-
return this.translateNode(filter);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
private translateNode(node: AstraVectorFilter): any {
|
|
50
|
-
// Handle primitive values and arrays
|
|
51
|
-
if (this.isRegex(node)) {
|
|
52
|
-
throw new Error('Regex is not supported in Astra DB');
|
|
53
|
-
}
|
|
54
|
-
if (this.isPrimitive(node) || Array.isArray(node)) {
|
|
55
|
-
return node;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const entries = Object.entries(node as Record<string, any>);
|
|
59
|
-
const translatedEntries = entries.map(([key, value]) => {
|
|
60
|
-
// Handle operators
|
|
61
|
-
if (this.isOperator(key)) {
|
|
62
|
-
return [key, this.translateOperatorValue(key, value)];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Handle nested paths and objects
|
|
66
|
-
return [key, this.translateNode(value)];
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return Object.fromEntries(translatedEntries);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private translateOperatorValue(operator: QueryOperator, value: any): any {
|
|
73
|
-
if (this.isBasicOperator(operator) || this.isNumericOperator(operator)) {
|
|
74
|
-
return this.normalizeComparisonValue(value);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (this.isArrayOperator(operator) && Array.isArray(value)) {
|
|
78
|
-
return this.normalizeArrayValues(value);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return this.translateNode(value);
|
|
82
|
-
}
|
|
83
|
-
}
|