@mastra/astra 0.10.3-alpha.0 → 0.11.0-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.
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +24 -0
- package/dist/_tsup-dts-rollup.d.cts +20 -5
- package/dist/_tsup-dts-rollup.d.ts +20 -5
- package/package.json +4 -4
- package/src/vector/filter.test.ts +38 -49
- package/src/vector/filter.ts +26 -4
- package/src/vector/index.test.ts +9 -17
- package/src/vector/index.ts +6 -5
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/astra@0.
|
|
2
|
+
> @mastra/astra@0.11.0-alpha.2 build /home/runner/work/mastra/mastra/stores/astra
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.5.0
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 7859ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/astra/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/astra/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 9584ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
20
|
[32mCJS[39m [1mdist/index.cjs [22m[32m14.42 KB[39m
|
|
21
|
-
[32mCJS[39m ⚡️ Build success in
|
|
21
|
+
[32mCJS[39m ⚡️ Build success in 514ms
|
|
22
22
|
[32mESM[39m [1mdist/index.js [22m[32m14.16 KB[39m
|
|
23
|
-
[32mESM[39m ⚡️ Build success in
|
|
23
|
+
[32mESM[39m ⚡️ Build success in 515ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @mastra/astra
|
|
2
2
|
|
|
3
|
+
## 0.11.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8a3bfd2: Update peerdeps to latest core
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [792c4c0]
|
|
12
|
+
- Updated dependencies [502fe05]
|
|
13
|
+
- Updated dependencies [4efcfa0]
|
|
14
|
+
- @mastra/core@0.10.7-alpha.3
|
|
15
|
+
|
|
16
|
+
## 0.10.3-alpha.1
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 144eb0b: [MASTRA-3669] Metadata Filter Types
|
|
21
|
+
- Updated dependencies [15e9d26]
|
|
22
|
+
- Updated dependencies [07d6d88]
|
|
23
|
+
- Updated dependencies [5d74aab]
|
|
24
|
+
- Updated dependencies [144eb0b]
|
|
25
|
+
- @mastra/core@0.10.7-alpha.2
|
|
26
|
+
|
|
3
27
|
## 0.10.3-alpha.0
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
2
|
+
import type { BlacklistedRootOperators } from '@mastra/core/vector/filter';
|
|
2
3
|
import type { CreateIndexParams } from '@mastra/core/vector';
|
|
3
4
|
import type { DeleteIndexParams } from '@mastra/core/vector';
|
|
4
5
|
import type { DeleteVectorParams } from '@mastra/core/vector';
|
|
5
6
|
import type { DescribeIndexParams } from '@mastra/core/vector';
|
|
6
7
|
import type { IndexStats } from '@mastra/core/vector';
|
|
8
|
+
import type { LogicalOperatorValueMap } from '@mastra/core/vector/filter';
|
|
7
9
|
import { MastraVector } from '@mastra/core/vector';
|
|
8
10
|
import type { OperatorSupport } from '@mastra/core/vector/filter';
|
|
11
|
+
import type { OperatorValueMap } from '@mastra/core/vector/filter';
|
|
9
12
|
import type { QueryResult } from '@mastra/core/vector';
|
|
10
13
|
import type { QueryVectorParams } from '@mastra/core/vector';
|
|
11
14
|
import type { UpdateVectorParams } from '@mastra/core/vector';
|
|
@@ -20,6 +23,8 @@ declare const ASTRA_PROMPT = "When querying Astra, you can ONLY use the operator
|
|
|
20
23
|
export { ASTRA_PROMPT }
|
|
21
24
|
export { ASTRA_PROMPT as ASTRA_PROMPT_alias_1 }
|
|
22
25
|
|
|
26
|
+
declare type AstraBlacklisted = BlacklistedRootOperators | '$nor' | '$size';
|
|
27
|
+
|
|
23
28
|
declare interface AstraDbOptions {
|
|
24
29
|
token: string;
|
|
25
30
|
endpoint: string;
|
|
@@ -33,14 +38,22 @@ export { AstraDbOptions as AstraDbOptions_alias_1 }
|
|
|
33
38
|
* Maintains MongoDB-compatible syntax while ensuring proper validation
|
|
34
39
|
* and normalization of values.
|
|
35
40
|
*/
|
|
36
|
-
export declare class AstraFilterTranslator extends BaseFilterTranslator {
|
|
41
|
+
export declare class AstraFilterTranslator extends BaseFilterTranslator<AstraVectorFilter> {
|
|
37
42
|
protected getSupportedOperators(): OperatorSupport;
|
|
38
|
-
translate(filter?:
|
|
43
|
+
translate(filter?: AstraVectorFilter): AstraVectorFilter;
|
|
39
44
|
private translateNode;
|
|
40
45
|
private translateOperatorValue;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
declare
|
|
48
|
+
declare type AstraLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
|
|
49
|
+
|
|
50
|
+
declare type AstraOperatorValueMap = Omit<OperatorValueMap, '$elemMatch' | '$regex' | '$options'> & {
|
|
51
|
+
$size: number;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
declare type AstraQueryVectorParams = QueryVectorParams<AstraVectorFilter>;
|
|
55
|
+
|
|
56
|
+
declare class AstraVector extends MastraVector<AstraVectorFilter> {
|
|
44
57
|
#private;
|
|
45
58
|
constructor({ token, endpoint, keyspace }: AstraDbOptions);
|
|
46
59
|
/**
|
|
@@ -62,7 +75,7 @@ declare class AstraVector extends MastraVector {
|
|
|
62
75
|
* @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.
|
|
63
76
|
*/
|
|
64
77
|
upsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]>;
|
|
65
|
-
transformFilter(filter?:
|
|
78
|
+
transformFilter(filter?: AstraVectorFilter): AstraVectorFilter;
|
|
66
79
|
/**
|
|
67
80
|
* Queries the specified collection using a vector and optional filter.
|
|
68
81
|
*
|
|
@@ -73,7 +86,7 @@ declare class AstraVector extends MastraVector {
|
|
|
73
86
|
* @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.
|
|
74
87
|
* @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.
|
|
75
88
|
*/
|
|
76
|
-
query({ indexName, queryVector, topK, filter, includeVector, }:
|
|
89
|
+
query({ indexName, queryVector, topK, filter, includeVector, }: AstraQueryVectorParams): Promise<QueryResult[]>;
|
|
77
90
|
/**
|
|
78
91
|
* Lists all collections in the database.
|
|
79
92
|
*
|
|
@@ -117,4 +130,6 @@ declare class AstraVector extends MastraVector {
|
|
|
117
130
|
export { AstraVector }
|
|
118
131
|
export { AstraVector as AstraVector_alias_1 }
|
|
119
132
|
|
|
133
|
+
export declare type AstraVectorFilter = VectorFilter<keyof AstraOperatorValueMap, AstraOperatorValueMap, AstraLogicalOperatorValueMap, AstraBlacklisted>;
|
|
134
|
+
|
|
120
135
|
export { }
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
2
|
+
import type { BlacklistedRootOperators } from '@mastra/core/vector/filter';
|
|
2
3
|
import type { CreateIndexParams } from '@mastra/core/vector';
|
|
3
4
|
import type { DeleteIndexParams } from '@mastra/core/vector';
|
|
4
5
|
import type { DeleteVectorParams } from '@mastra/core/vector';
|
|
5
6
|
import type { DescribeIndexParams } from '@mastra/core/vector';
|
|
6
7
|
import type { IndexStats } from '@mastra/core/vector';
|
|
8
|
+
import type { LogicalOperatorValueMap } from '@mastra/core/vector/filter';
|
|
7
9
|
import { MastraVector } from '@mastra/core/vector';
|
|
8
10
|
import type { OperatorSupport } from '@mastra/core/vector/filter';
|
|
11
|
+
import type { OperatorValueMap } from '@mastra/core/vector/filter';
|
|
9
12
|
import type { QueryResult } from '@mastra/core/vector';
|
|
10
13
|
import type { QueryVectorParams } from '@mastra/core/vector';
|
|
11
14
|
import type { UpdateVectorParams } from '@mastra/core/vector';
|
|
@@ -20,6 +23,8 @@ declare const ASTRA_PROMPT = "When querying Astra, you can ONLY use the operator
|
|
|
20
23
|
export { ASTRA_PROMPT }
|
|
21
24
|
export { ASTRA_PROMPT as ASTRA_PROMPT_alias_1 }
|
|
22
25
|
|
|
26
|
+
declare type AstraBlacklisted = BlacklistedRootOperators | '$nor' | '$size';
|
|
27
|
+
|
|
23
28
|
declare interface AstraDbOptions {
|
|
24
29
|
token: string;
|
|
25
30
|
endpoint: string;
|
|
@@ -33,14 +38,22 @@ export { AstraDbOptions as AstraDbOptions_alias_1 }
|
|
|
33
38
|
* Maintains MongoDB-compatible syntax while ensuring proper validation
|
|
34
39
|
* and normalization of values.
|
|
35
40
|
*/
|
|
36
|
-
export declare class AstraFilterTranslator extends BaseFilterTranslator {
|
|
41
|
+
export declare class AstraFilterTranslator extends BaseFilterTranslator<AstraVectorFilter> {
|
|
37
42
|
protected getSupportedOperators(): OperatorSupport;
|
|
38
|
-
translate(filter?:
|
|
43
|
+
translate(filter?: AstraVectorFilter): AstraVectorFilter;
|
|
39
44
|
private translateNode;
|
|
40
45
|
private translateOperatorValue;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
declare
|
|
48
|
+
declare type AstraLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
|
|
49
|
+
|
|
50
|
+
declare type AstraOperatorValueMap = Omit<OperatorValueMap, '$elemMatch' | '$regex' | '$options'> & {
|
|
51
|
+
$size: number;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
declare type AstraQueryVectorParams = QueryVectorParams<AstraVectorFilter>;
|
|
55
|
+
|
|
56
|
+
declare class AstraVector extends MastraVector<AstraVectorFilter> {
|
|
44
57
|
#private;
|
|
45
58
|
constructor({ token, endpoint, keyspace }: AstraDbOptions);
|
|
46
59
|
/**
|
|
@@ -62,7 +75,7 @@ declare class AstraVector extends MastraVector {
|
|
|
62
75
|
* @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.
|
|
63
76
|
*/
|
|
64
77
|
upsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]>;
|
|
65
|
-
transformFilter(filter?:
|
|
78
|
+
transformFilter(filter?: AstraVectorFilter): AstraVectorFilter;
|
|
66
79
|
/**
|
|
67
80
|
* Queries the specified collection using a vector and optional filter.
|
|
68
81
|
*
|
|
@@ -73,7 +86,7 @@ declare class AstraVector extends MastraVector {
|
|
|
73
86
|
* @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.
|
|
74
87
|
* @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.
|
|
75
88
|
*/
|
|
76
|
-
query({ indexName, queryVector, topK, filter, includeVector, }:
|
|
89
|
+
query({ indexName, queryVector, topK, filter, includeVector, }: AstraQueryVectorParams): Promise<QueryResult[]>;
|
|
77
90
|
/**
|
|
78
91
|
* Lists all collections in the database.
|
|
79
92
|
*
|
|
@@ -117,4 +130,6 @@ declare class AstraVector extends MastraVector {
|
|
|
117
130
|
export { AstraVector }
|
|
118
131
|
export { AstraVector as AstraVector_alias_1 }
|
|
119
132
|
|
|
133
|
+
export declare type AstraVectorFilter = VectorFilter<keyof AstraOperatorValueMap, AstraOperatorValueMap, AstraLogicalOperatorValueMap, AstraBlacklisted>;
|
|
134
|
+
|
|
120
135
|
export { }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/astra",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0-alpha.2",
|
|
4
4
|
"description": "Astra DB provider for Mastra - includes vector store capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,15 +25,15 @@
|
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@microsoft/api-extractor": "^7.52.8",
|
|
27
27
|
"@types/node": "^20.19.0",
|
|
28
|
-
"eslint": "^9.
|
|
28
|
+
"eslint": "^9.29.0",
|
|
29
29
|
"tsup": "^8.5.0",
|
|
30
30
|
"typescript": "^5.8.3",
|
|
31
31
|
"vitest": "^3.2.3",
|
|
32
32
|
"@internal/lint": "0.0.13",
|
|
33
|
-
"@mastra/core": "0.10.7-alpha.
|
|
33
|
+
"@mastra/core": "0.10.7-alpha.3"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@mastra/core": ">=0.10.
|
|
36
|
+
"@mastra/core": ">=0.10.7-0 <0.11.0-0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
2
|
|
|
3
|
+
import type { AstraVectorFilter } from './filter';
|
|
3
4
|
import { AstraFilterTranslator } from './filter';
|
|
4
5
|
|
|
5
6
|
describe('AstraFilterTranslator', () => {
|
|
@@ -12,12 +13,12 @@ describe('AstraFilterTranslator', () => {
|
|
|
12
13
|
// Basic Filter Operations
|
|
13
14
|
describe('basic operations', () => {
|
|
14
15
|
it('handles simple equality', () => {
|
|
15
|
-
const filter = { field: 'value' };
|
|
16
|
+
const filter: AstraVectorFilter = { 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: AstraVectorFilter = {
|
|
21
22
|
age: { $gt: 25 },
|
|
22
23
|
score: { $lte: 100 },
|
|
23
24
|
};
|
|
@@ -25,7 +26,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
it('handles valid multiple operators on same field', () => {
|
|
28
|
-
const filter = {
|
|
29
|
+
const filter: AstraVectorFilter = {
|
|
29
30
|
price: { $gt: 100, $lt: 200 },
|
|
30
31
|
quantity: { $gte: 10, $lte: 20 },
|
|
31
32
|
};
|
|
@@ -33,7 +34,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
33
34
|
});
|
|
34
35
|
|
|
35
36
|
it('handles null values correctly', () => {
|
|
36
|
-
const filter = {
|
|
37
|
+
const filter: AstraVectorFilter = {
|
|
37
38
|
field: null,
|
|
38
39
|
other: { $eq: null },
|
|
39
40
|
};
|
|
@@ -41,7 +42,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
41
42
|
});
|
|
42
43
|
|
|
43
44
|
it('throws on unsupported combinations', () => {
|
|
44
|
-
const filter = {
|
|
45
|
+
const filter: AstraVectorFilter = {
|
|
45
46
|
field: { $gt: 100, $lt: 200 },
|
|
46
47
|
};
|
|
47
48
|
expect(translator.translate(filter)).toEqual(filter);
|
|
@@ -51,14 +52,14 @@ describe('AstraFilterTranslator', () => {
|
|
|
51
52
|
// Array Operations
|
|
52
53
|
describe('array operations', () => {
|
|
53
54
|
it('handles array operators', () => {
|
|
54
|
-
const filter = {
|
|
55
|
+
const filter: AstraVectorFilter = {
|
|
55
56
|
tags: { $all: ['tag1', 'tag2'] },
|
|
56
57
|
categories: { $in: ['A', 'B'] },
|
|
57
58
|
};
|
|
58
59
|
expect(translator.translate(filter)).toEqual(filter);
|
|
59
60
|
});
|
|
60
61
|
it('handles empty array values', () => {
|
|
61
|
-
const filter = {
|
|
62
|
+
const filter: AstraVectorFilter = {
|
|
62
63
|
tags: { $in: [] },
|
|
63
64
|
categories: { $all: [] },
|
|
64
65
|
};
|
|
@@ -66,7 +67,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
66
67
|
});
|
|
67
68
|
|
|
68
69
|
it('handles nested array operators', () => {
|
|
69
|
-
const filter = {
|
|
70
|
+
const filter: AstraVectorFilter = {
|
|
70
71
|
$and: [{ tags: { $all: ['tag1', 'tag2'] } }, { 'nested.array': { $in: [1, 2, 3] } }],
|
|
71
72
|
};
|
|
72
73
|
expect(translator.translate(filter)).toEqual(filter);
|
|
@@ -76,14 +77,14 @@ describe('AstraFilterTranslator', () => {
|
|
|
76
77
|
// Logical Operators
|
|
77
78
|
describe('logical operators', () => {
|
|
78
79
|
it('handles logical operators', () => {
|
|
79
|
-
const filter = {
|
|
80
|
+
const filter: AstraVectorFilter = {
|
|
80
81
|
$or: [{ status: 'active' }, { age: { $gt: 25 } }],
|
|
81
82
|
};
|
|
82
83
|
expect(translator.translate(filter)).toEqual(filter);
|
|
83
84
|
});
|
|
84
85
|
|
|
85
86
|
it('handles nested logical operators', () => {
|
|
86
|
-
const filter = {
|
|
87
|
+
const filter: AstraVectorFilter = {
|
|
87
88
|
$and: [
|
|
88
89
|
{ status: 'active' },
|
|
89
90
|
{ $or: [{ category: { $in: ['A', 'B'] } }, { $and: [{ price: { $gt: 100 } }, { stock: { $lt: 50 } }] }] },
|
|
@@ -93,7 +94,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
it('handles empty conditions in logical operators', () => {
|
|
96
|
-
const filter = {
|
|
97
|
+
const filter: AstraVectorFilter = {
|
|
97
98
|
$and: [],
|
|
98
99
|
$or: [{}],
|
|
99
100
|
field: 'value',
|
|
@@ -147,7 +148,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
147
148
|
|
|
148
149
|
expect(() =>
|
|
149
150
|
translator.translate({
|
|
150
|
-
$or: [{ $in: ['value1', 'value2'] }],
|
|
151
|
+
$or: [{ $in: ['value1', 'value2'] as any }],
|
|
151
152
|
}),
|
|
152
153
|
).toThrow(/Logical operators must contain field conditions/);
|
|
153
154
|
});
|
|
@@ -158,7 +159,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
158
159
|
field: {
|
|
159
160
|
$gt: {
|
|
160
161
|
$or: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
161
|
-
},
|
|
162
|
+
} as any,
|
|
162
163
|
},
|
|
163
164
|
}),
|
|
164
165
|
).toThrow();
|
|
@@ -169,7 +170,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
169
170
|
$in: [
|
|
170
171
|
{
|
|
171
172
|
$and: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
172
|
-
},
|
|
173
|
+
} as any,
|
|
173
174
|
],
|
|
174
175
|
},
|
|
175
176
|
}),
|
|
@@ -182,7 +183,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
182
183
|
field: {
|
|
183
184
|
$gt: {
|
|
184
185
|
$or: [{ subfield: 'value1' }, { subfield: 'value2' }],
|
|
185
|
-
},
|
|
186
|
+
} as any,
|
|
186
187
|
},
|
|
187
188
|
}),
|
|
188
189
|
).toThrow();
|
|
@@ -200,7 +201,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
200
201
|
|
|
201
202
|
it('throws error for $not if not an object', () => {
|
|
202
203
|
expect(() => translator.translate({ $not: 'value' })).toThrow();
|
|
203
|
-
expect(() => translator.translate({ $not: [{ field: 'value' }] })).toThrow();
|
|
204
|
+
expect(() => translator.translate({ $not: [{ field: 'value' }] } as any)).toThrow();
|
|
204
205
|
});
|
|
205
206
|
|
|
206
207
|
it('throws error for $not if empty', () => {
|
|
@@ -211,7 +212,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
211
212
|
// Nested Objects and Fields
|
|
212
213
|
describe('nested objects and fields', () => {
|
|
213
214
|
it('handles nested objects', () => {
|
|
214
|
-
const filter = {
|
|
215
|
+
const filter: AstraVectorFilter = {
|
|
215
216
|
'user.profile.age': { $gt: 25 },
|
|
216
217
|
'user.status': 'active',
|
|
217
218
|
};
|
|
@@ -219,7 +220,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
219
220
|
});
|
|
220
221
|
|
|
221
222
|
it('handles deeply nested field paths', () => {
|
|
222
|
-
const filter = {
|
|
223
|
+
const filter: AstraVectorFilter = {
|
|
223
224
|
'user.profile.address.city': { $eq: 'New York' },
|
|
224
225
|
'deep.nested.field': { $gt: 100 },
|
|
225
226
|
};
|
|
@@ -227,38 +228,28 @@ describe('AstraFilterTranslator', () => {
|
|
|
227
228
|
});
|
|
228
229
|
|
|
229
230
|
it('preserves nested empty objects', () => {
|
|
230
|
-
const filter = {
|
|
231
|
+
const filter: AstraVectorFilter = {
|
|
231
232
|
status: 'active',
|
|
232
233
|
metadata: {},
|
|
233
|
-
user: {
|
|
234
|
-
|
|
235
|
-
settings: { theme: null },
|
|
236
|
-
},
|
|
234
|
+
'user.profile': {},
|
|
235
|
+
'usersettings.theme': null,
|
|
237
236
|
};
|
|
238
237
|
expect(translator.translate(filter)).toEqual(filter);
|
|
239
238
|
});
|
|
240
239
|
|
|
241
240
|
it('handles mix of operators and empty objects', () => {
|
|
242
|
-
const filter = {
|
|
241
|
+
const filter: AstraVectorFilter = {
|
|
243
242
|
tags: { $in: ['a', 'b'] },
|
|
244
243
|
metadata: {},
|
|
245
|
-
nested: {
|
|
246
|
-
|
|
247
|
-
empty: {},
|
|
248
|
-
},
|
|
244
|
+
'nested.field': { $eq: 'value' },
|
|
245
|
+
'nested.empty': {},
|
|
249
246
|
};
|
|
250
247
|
expect(translator.translate(filter)).toEqual(filter);
|
|
251
248
|
});
|
|
252
249
|
|
|
253
250
|
it('handles deeply nested operators', () => {
|
|
254
|
-
const filter = {
|
|
255
|
-
user: {
|
|
256
|
-
profile: {
|
|
257
|
-
preferences: {
|
|
258
|
-
theme: { $in: ['dark', 'light'] },
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
},
|
|
251
|
+
const filter: AstraVectorFilter = {
|
|
252
|
+
'user.profile.preferences.theme': { $in: ['dark', 'light'] },
|
|
262
253
|
};
|
|
263
254
|
expect(translator.translate(filter)).toEqual(filter);
|
|
264
255
|
});
|
|
@@ -268,13 +259,13 @@ describe('AstraFilterTranslator', () => {
|
|
|
268
259
|
describe('special cases', () => {
|
|
269
260
|
it('handles empty filters', () => {
|
|
270
261
|
expect(translator.translate({})).toEqual({});
|
|
271
|
-
expect(translator.translate(null
|
|
272
|
-
expect(translator.translate(undefined
|
|
262
|
+
expect(translator.translate(null)).toEqual(null);
|
|
263
|
+
expect(translator.translate(undefined)).toEqual(undefined);
|
|
273
264
|
});
|
|
274
265
|
|
|
275
266
|
it('normalizes dates', () => {
|
|
276
267
|
const date = new Date('2024-01-01');
|
|
277
|
-
const filter = { timestamp: { $gt: date } };
|
|
268
|
+
const filter: AstraVectorFilter = { timestamp: { $gt: date } };
|
|
278
269
|
expect(translator.translate(filter)).toEqual({
|
|
279
270
|
timestamp: { $gt: date.toISOString() },
|
|
280
271
|
});
|
|
@@ -293,7 +284,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
293
284
|
|
|
294
285
|
describe('operator validation', () => {
|
|
295
286
|
it('ensure all operator filters are supported', () => {
|
|
296
|
-
const supportedFilters = [
|
|
287
|
+
const supportedFilters: AstraVectorFilter[] = [
|
|
297
288
|
// Basic comparison operators
|
|
298
289
|
{ field: { $eq: 'value' } },
|
|
299
290
|
{ field: { $ne: 'value' } },
|
|
@@ -313,11 +304,9 @@ describe('AstraFilterTranslator', () => {
|
|
|
313
304
|
{ $and: [{ field1: 'value1' }, { field2: 'value2' }] },
|
|
314
305
|
{ $or: [{ field1: 'value1' }, { field2: 'value2' }] },
|
|
315
306
|
|
|
316
|
-
{ $and: { field: 'value' } },
|
|
317
|
-
{ $or: { field: 'value' } },
|
|
318
307
|
{ $not: { field: 'value' } },
|
|
319
308
|
|
|
320
|
-
{ $or: [{ $and: { field1: 'value1' } }, { $not: { field2: 'value2' } }] },
|
|
309
|
+
{ $or: [{ $and: [{ field1: 'value1' }] }, { $not: { field2: 'value2' } }] },
|
|
321
310
|
|
|
322
311
|
{ field: { $not: { $eq: 'value' } } },
|
|
323
312
|
{ field: { $not: { $in: ['value1', 'value2'] } } },
|
|
@@ -333,16 +322,16 @@ describe('AstraFilterTranslator', () => {
|
|
|
333
322
|
});
|
|
334
323
|
|
|
335
324
|
it('throws on unsupported operators', () => {
|
|
336
|
-
expect(() => translator.translate({ field: { $regex: 'value' } })).toThrow('Unsupported operator: $regex');
|
|
337
|
-
const filter = { field: /pattern/i };
|
|
325
|
+
expect(() => translator.translate({ field: { $regex: 'value' } as any })).toThrow('Unsupported operator: $regex');
|
|
326
|
+
const filter: any = { field: /pattern/i };
|
|
338
327
|
expect(() => translator.translate(filter)).toThrow();
|
|
339
|
-
expect(() => translator.translate({ $nor: [{ field: 'value' }] })).toThrow('Unsupported operator: $nor');
|
|
340
|
-
expect(() => translator.translate({ field: { $elemMatch: { $gt: 5 } } })).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(
|
|
341
330
|
'Unsupported operator: $elemMatch',
|
|
342
331
|
);
|
|
343
332
|
});
|
|
344
333
|
it('throws error for non-logical operators at top level', () => {
|
|
345
|
-
const invalidFilters = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $exists: true }];
|
|
334
|
+
const invalidFilters: any = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $exists: true }];
|
|
346
335
|
|
|
347
336
|
invalidFilters.forEach(filter => {
|
|
348
337
|
expect(() => translator.translate(filter)).toThrow(/Invalid top-level operator/);
|
|
@@ -350,7 +339,7 @@ describe('AstraFilterTranslator', () => {
|
|
|
350
339
|
});
|
|
351
340
|
|
|
352
341
|
it('allows logical operators at top level', () => {
|
|
353
|
-
const validFilters = [
|
|
342
|
+
const validFilters: AstraVectorFilter[] = [
|
|
354
343
|
{ $and: [{ field: 'value' }] },
|
|
355
344
|
{ $or: [{ field: 'value' }] },
|
|
356
345
|
{ $not: { field: 'value' } },
|
package/src/vector/filter.ts
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
2
|
-
import type {
|
|
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
|
+
>;
|
|
3
25
|
|
|
4
26
|
/**
|
|
5
27
|
* Translator for Astra DB filter queries.
|
|
6
28
|
* Maintains MongoDB-compatible syntax while ensuring proper validation
|
|
7
29
|
* and normalization of values.
|
|
8
30
|
*/
|
|
9
|
-
export class AstraFilterTranslator extends BaseFilterTranslator {
|
|
31
|
+
export class AstraFilterTranslator extends BaseFilterTranslator<AstraVectorFilter> {
|
|
10
32
|
protected override getSupportedOperators(): OperatorSupport {
|
|
11
33
|
return {
|
|
12
34
|
...BaseFilterTranslator.DEFAULT_OPERATORS,
|
|
@@ -17,14 +39,14 @@ export class AstraFilterTranslator extends BaseFilterTranslator {
|
|
|
17
39
|
};
|
|
18
40
|
}
|
|
19
41
|
|
|
20
|
-
translate(filter?:
|
|
42
|
+
translate(filter?: AstraVectorFilter): AstraVectorFilter {
|
|
21
43
|
if (this.isEmpty(filter)) return filter;
|
|
22
44
|
this.validateFilter(filter);
|
|
23
45
|
|
|
24
46
|
return this.translateNode(filter);
|
|
25
47
|
}
|
|
26
48
|
|
|
27
|
-
private translateNode(node:
|
|
49
|
+
private translateNode(node: AstraVectorFilter): any {
|
|
28
50
|
// Handle primitive values and arrays
|
|
29
51
|
if (this.isRegex(node)) {
|
|
30
52
|
throw new Error('Regex is not supported in Astra DB');
|
package/src/vector/index.test.ts
CHANGED
|
@@ -297,7 +297,7 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
297
297
|
vectorDB.query({
|
|
298
298
|
indexName: testIndexName2,
|
|
299
299
|
queryVector: [1, 0, 0, 0],
|
|
300
|
-
filter: { tags: { $all: 'not-an-array' } },
|
|
300
|
+
filter: { tags: { $all: 'not-an-array' as any } },
|
|
301
301
|
}),
|
|
302
302
|
).rejects.toThrow();
|
|
303
303
|
});
|
|
@@ -307,15 +307,7 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
307
307
|
vectorDB.query({
|
|
308
308
|
indexName: testIndexName2,
|
|
309
309
|
queryVector: [1, 0, 0, 0],
|
|
310
|
-
filter: { tags: { $in: null } },
|
|
311
|
-
}),
|
|
312
|
-
).rejects.toThrow();
|
|
313
|
-
|
|
314
|
-
await expect(
|
|
315
|
-
vectorDB.query({
|
|
316
|
-
indexName: testIndexName2,
|
|
317
|
-
queryVector: [1, 0, 0, 0],
|
|
318
|
-
filter: { tags: { $all: 'not-an-array' } },
|
|
310
|
+
filter: { tags: { $in: null as any } },
|
|
319
311
|
}),
|
|
320
312
|
).rejects.toThrow();
|
|
321
313
|
});
|
|
@@ -327,7 +319,7 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
327
319
|
vectorDB.query({
|
|
328
320
|
indexName: testIndexName2,
|
|
329
321
|
queryVector: [1, 0, 0, 0],
|
|
330
|
-
filter: { field: { $in: val } },
|
|
322
|
+
filter: { field: { $in: val as any } },
|
|
331
323
|
}),
|
|
332
324
|
).rejects.toThrow();
|
|
333
325
|
}
|
|
@@ -340,7 +332,7 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
340
332
|
vectorDB.query({
|
|
341
333
|
indexName: testIndexName2,
|
|
342
334
|
queryVector: [1, 0, 0, 0],
|
|
343
|
-
filter: { field: { $nin: val } },
|
|
335
|
+
filter: { field: { $nin: val as any } },
|
|
344
336
|
}),
|
|
345
337
|
).rejects.toThrow();
|
|
346
338
|
}
|
|
@@ -353,7 +345,7 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
353
345
|
vectorDB.query({
|
|
354
346
|
indexName: testIndexName2,
|
|
355
347
|
queryVector: [1, 0, 0, 0],
|
|
356
|
-
filter: { field: { $all: val } },
|
|
348
|
+
filter: { field: { $all: val as any } },
|
|
357
349
|
}),
|
|
358
350
|
).rejects.toThrow();
|
|
359
351
|
}
|
|
@@ -366,7 +358,7 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
366
358
|
vectorDB.query({
|
|
367
359
|
indexName: testIndexName2,
|
|
368
360
|
queryVector: [1, 0, 0, 0],
|
|
369
|
-
filter: { field: { $exists: val } },
|
|
361
|
+
filter: { field: { $exists: val as any } },
|
|
370
362
|
}),
|
|
371
363
|
).rejects.toThrow();
|
|
372
364
|
}
|
|
@@ -395,9 +387,9 @@ describe.skip('AstraVector Integration Tests', () => {
|
|
|
395
387
|
indexName: testIndexName2,
|
|
396
388
|
queryVector: [1, 0, 0, 0],
|
|
397
389
|
filter: {
|
|
398
|
-
field1: { $in: 'not-array' },
|
|
399
|
-
field2: { $exists: 'not-boolean' },
|
|
400
|
-
field3: { $gt: 'not-number' },
|
|
390
|
+
field1: { $in: 'not-array' as any },
|
|
391
|
+
field2: { $exists: 'not-boolean' as any },
|
|
392
|
+
field3: { $gt: 'not-number' as any },
|
|
401
393
|
},
|
|
402
394
|
}),
|
|
403
395
|
).rejects.toThrow();
|
package/src/vector/index.ts
CHANGED
|
@@ -13,8 +13,7 @@ import type {
|
|
|
13
13
|
DeleteVectorParams,
|
|
14
14
|
UpdateVectorParams,
|
|
15
15
|
} from '@mastra/core/vector';
|
|
16
|
-
import type {
|
|
17
|
-
|
|
16
|
+
import type { AstraVectorFilter } from './filter';
|
|
18
17
|
import { AstraFilterTranslator } from './filter';
|
|
19
18
|
|
|
20
19
|
// Mastra and Astra DB agree on cosine and euclidean, but Astra DB uses dot_product instead of dotproduct.
|
|
@@ -30,7 +29,9 @@ export interface AstraDbOptions {
|
|
|
30
29
|
keyspace?: string;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
type AstraQueryVectorParams = QueryVectorParams<AstraVectorFilter>;
|
|
33
|
+
|
|
34
|
+
export class AstraVector extends MastraVector<AstraVectorFilter> {
|
|
34
35
|
readonly #db: Db;
|
|
35
36
|
|
|
36
37
|
constructor({ token, endpoint, keyspace }: AstraDbOptions) {
|
|
@@ -114,7 +115,7 @@ export class AstraVector extends MastraVector {
|
|
|
114
115
|
return vectorIds;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
transformFilter(filter?:
|
|
118
|
+
transformFilter(filter?: AstraVectorFilter) {
|
|
118
119
|
const translator = new AstraFilterTranslator();
|
|
119
120
|
return translator.translate(filter);
|
|
120
121
|
}
|
|
@@ -135,7 +136,7 @@ export class AstraVector extends MastraVector {
|
|
|
135
136
|
topK = 10,
|
|
136
137
|
filter,
|
|
137
138
|
includeVector = false,
|
|
138
|
-
}:
|
|
139
|
+
}: AstraQueryVectorParams): Promise<QueryResult[]> {
|
|
139
140
|
const collection = this.#db.collection(indexName);
|
|
140
141
|
|
|
141
142
|
const translatedFilter = this.transformFilter(filter);
|