@mastra/opensearch 1.1.1 → 1.1.2-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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-rag-retrieval.md +7 -5
- package/dist/docs/references/reference-rag-vector-databases.md +98 -2
- package/dist/index.cjs +85 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +85 -1
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-opensearch
|
|
|
3
3
|
description: Documentation for @mastra/opensearch. Use when working with @mastra/opensearch APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/opensearch"
|
|
6
|
-
version: "1.1.
|
|
6
|
+
version: "1.1.2-alpha.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -50,23 +50,25 @@ console.log(results)
|
|
|
50
50
|
|
|
51
51
|
The `topK` parameter specifies the maximum number of most similar results to return from the vector search.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Each result includes an `id`, a similarity `score`, and the stored `metadata`. When you store chunk text in metadata, it's available as `metadata.text`:
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
56
|
[
|
|
57
57
|
{
|
|
58
|
-
|
|
58
|
+
id: 'chunk-1',
|
|
59
59
|
score: 0.89,
|
|
60
|
-
metadata: { source: 'article1.txt' },
|
|
60
|
+
metadata: { text: 'Climate change poses significant challenges...', source: 'article1.txt' },
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
|
-
|
|
63
|
+
id: 'chunk-2',
|
|
64
64
|
score: 0.82,
|
|
65
|
-
metadata: { source: 'article1.txt' },
|
|
65
|
+
metadata: { text: 'Rising temperatures affect crop yields...', source: 'article1.txt' },
|
|
66
66
|
},
|
|
67
67
|
]
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
Results can also include `vector` when you set `includeVector: true`, and `document` when the store returns the original document (Chroma only).
|
|
71
|
+
|
|
70
72
|
## Advanced retrieval options
|
|
71
73
|
|
|
72
74
|
### Metadata Filtering
|
|
@@ -54,6 +54,29 @@ const results = await store.hybridQuery({
|
|
|
54
54
|
|
|
55
55
|
See the [MongoDB vector reference](https://mastra.ai/reference/vectors/mongodb) for details on `createSearchIndex()`, `textQuery()`, and `hybridQuery()`.
|
|
56
56
|
|
|
57
|
+
### Automated Embedding
|
|
58
|
+
|
|
59
|
+
MongoDB can generate the embeddings itself, so you don't need an embedding provider in your application. Create the index with `autoEmbed` and a Voyage AI model, write plain text, and search with a query string:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
await store.createIndex({
|
|
63
|
+
indexName: 'myCollection',
|
|
64
|
+
autoEmbed: { model: 'voyage-4' },
|
|
65
|
+
})
|
|
66
|
+
await store.upsert({
|
|
67
|
+
indexName: 'myCollection',
|
|
68
|
+
documents: chunks.map(chunk => chunk.text),
|
|
69
|
+
metadata: chunks.map(chunk => ({ text: chunk.text })),
|
|
70
|
+
})
|
|
71
|
+
const results = await store.query({
|
|
72
|
+
indexName: 'myCollection',
|
|
73
|
+
queryText: 'search terms',
|
|
74
|
+
topK: 10,
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Automated Embedding is a MongoDB Preview feature and needs a deployment where it's available. See the [MongoDB vector reference](https://mastra.ai/reference/vectors/mongodb) for the supported options and requirements.
|
|
79
|
+
|
|
57
80
|
**PgVector**:
|
|
58
81
|
|
|
59
82
|
```ts
|
|
@@ -207,7 +230,7 @@ await store.upsert({
|
|
|
207
230
|
**libSQL**:
|
|
208
231
|
|
|
209
232
|
```ts
|
|
210
|
-
import { LibSQLVector } from '@mastra/
|
|
233
|
+
import { LibSQLVector } from '@mastra/libsql'
|
|
211
234
|
|
|
212
235
|
const store = new LibSQLVector({
|
|
213
236
|
id: 'libsql-vector',
|
|
@@ -248,6 +271,34 @@ await store.upsert({
|
|
|
248
271
|
})
|
|
249
272
|
```
|
|
250
273
|
|
|
274
|
+
**Weaviate**:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { WeaviateVector } from '@mastra/weaviate'
|
|
278
|
+
|
|
279
|
+
const store = new WeaviateVector({
|
|
280
|
+
id: 'weaviate-vector',
|
|
281
|
+
httpHost: process.env.WEAVIATE_HOST,
|
|
282
|
+
httpPort: 443,
|
|
283
|
+
httpSecure: true,
|
|
284
|
+
grpcHost: process.env.WEAVIATE_GRPC_HOST,
|
|
285
|
+
grpcPort: 443,
|
|
286
|
+
grpcSecure: true,
|
|
287
|
+
apiKey: process.env.WEAVIATE_API_KEY,
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
await store.createIndex({
|
|
291
|
+
indexName: 'myCollection',
|
|
292
|
+
dimension: 1536,
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
await store.upsert({
|
|
296
|
+
indexName: 'myCollection',
|
|
297
|
+
vectors: embeddings,
|
|
298
|
+
metadata: chunks.map(chunk => ({ text: chunk.text })),
|
|
299
|
+
})
|
|
300
|
+
```
|
|
301
|
+
|
|
251
302
|
**Cloudflare**:
|
|
252
303
|
|
|
253
304
|
```ts
|
|
@@ -317,6 +368,29 @@ await store.upsert({
|
|
|
317
368
|
|
|
318
369
|
For detailed setup instructions and best practices, see the [official Elasticsearch documentation](https://www.elastic.co/docs/solutions/search/get-started).
|
|
319
370
|
|
|
371
|
+
**Azure AI Search**:
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
import { AzureAISearchVector } from '@mastra/azure-ai-search'
|
|
375
|
+
|
|
376
|
+
const store = new AzureAISearchVector({
|
|
377
|
+
id: 'azure-search-vectors',
|
|
378
|
+
endpoint: process.env.AZURE_AI_SEARCH_ENDPOINT!,
|
|
379
|
+
credential: process.env.AZURE_AI_SEARCH_CREDENTIAL!,
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
await store.createIndex({
|
|
383
|
+
indexName: 'my-collection',
|
|
384
|
+
dimension: 1536,
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
await store.upsert({
|
|
388
|
+
indexName: 'my-collection',
|
|
389
|
+
vectors: embeddings,
|
|
390
|
+
metadata: chunks.map(chunk => ({ text: chunk.text })),
|
|
391
|
+
})
|
|
392
|
+
```
|
|
393
|
+
|
|
320
394
|
**Couchbase**:
|
|
321
395
|
|
|
322
396
|
```ts
|
|
@@ -534,6 +608,17 @@ Namespace names must:
|
|
|
534
608
|
|
|
535
609
|
- Example: `_namespace` isn't valid (starts with underscore)
|
|
536
610
|
|
|
611
|
+
**Weaviate**:
|
|
612
|
+
|
|
613
|
+
Index names map to Weaviate collections, which:
|
|
614
|
+
|
|
615
|
+
- Are capitalized by Weaviate (the first letter is upper-cased)
|
|
616
|
+
- Should contain only letters, numbers, and the `_` character
|
|
617
|
+
- Must start with a letter, since only the first character is upper-cased (a leading digit or symbol stays invalid)
|
|
618
|
+
- Preserve the original Mastra index name in the collection description, so `listIndexes()` and `describeIndex()` return the name you supplied
|
|
619
|
+
- Example: `my_collection` is stored as `My_collection` and returned as `my_collection`
|
|
620
|
+
- Example: `123_collection` isn't valid (starts with a digit)
|
|
621
|
+
|
|
537
622
|
**Cloudflare**:
|
|
538
623
|
|
|
539
624
|
Index names must:
|
|
@@ -587,6 +672,17 @@ Index names must:
|
|
|
587
672
|
- Example: `myindex-` isn't valid (ends with hyphen)
|
|
588
673
|
- Example: `MyIndex` isn't valid (contains uppercase letters)
|
|
589
674
|
|
|
675
|
+
**Azure AI Search**:
|
|
676
|
+
|
|
677
|
+
Index names must:
|
|
678
|
+
|
|
679
|
+
- Use only lowercase letters, numbers, dashes (`-`), and underscore (`_`) characters
|
|
680
|
+
- Not start or end with a dash
|
|
681
|
+
- Be between 2 and 128 characters long
|
|
682
|
+
- Example: `my-index-123` and `my_index` are valid
|
|
683
|
+
- Example: `MyIndex` isn't valid (contains uppercase letters)
|
|
684
|
+
- Example: `my-index-` isn't valid (ends with a dash)
|
|
685
|
+
|
|
590
686
|
### Upserting Embeddings
|
|
591
687
|
|
|
592
688
|
After creating an index, you can store embeddings along with their basic metadata:
|
|
@@ -650,7 +746,7 @@ Key metadata considerations:
|
|
|
650
746
|
|
|
651
747
|
## Deleting vectors
|
|
652
748
|
|
|
653
|
-
|
|
749
|
+
Use `deleteVectors` with a metadata filter to remove embeddings associated with a document. This is useful for cleaning up stale vectors after a document is deleted or updated.
|
|
654
750
|
|
|
655
751
|
### Delete by Metadata Filter
|
|
656
752
|
|
package/dist/index.cjs
CHANGED
|
@@ -705,6 +705,91 @@ var OpenSearchVector = class extends _mastra_core_vector.MastraVector {
|
|
|
705
705
|
}
|
|
706
706
|
};
|
|
707
707
|
//#endregion
|
|
708
|
+
//#region src/vector/prompt.ts
|
|
709
|
+
/**
|
|
710
|
+
* Vector store prompt for OpenSearch. This prompt details supported filter operators, syntax, and usage examples.
|
|
711
|
+
* Use this as a guide for constructing valid filters for OpenSearch vector queries in Mastra.
|
|
712
|
+
*/
|
|
713
|
+
const OPENSEARCH_PROMPT = `When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.
|
|
714
|
+
Important: Do not explain how to construct the filter—use the specified operators and fields to search the content and return relevant results.
|
|
715
|
+
If a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.
|
|
716
|
+
|
|
717
|
+
Basic Comparison Operators:
|
|
718
|
+
- $eq: Exact match (default for field: value)
|
|
719
|
+
Example: { "category": "electronics" }
|
|
720
|
+
- $ne: Not equal
|
|
721
|
+
Example: { "category": { "$ne": "electronics" } }
|
|
722
|
+
- $gt: Greater than
|
|
723
|
+
Example: { "price": { "$gt": 100 } }
|
|
724
|
+
- $gte: Greater than or equal
|
|
725
|
+
Example: { "price": { "$gte": 100 } }
|
|
726
|
+
- $lt: Less than
|
|
727
|
+
Example: { "price": { "$lt": 100 } }
|
|
728
|
+
- $lte: Less than or equal
|
|
729
|
+
Example: { "price": { "$lte": 100 } }
|
|
730
|
+
|
|
731
|
+
Array Operators:
|
|
732
|
+
- $in: Match any value in array
|
|
733
|
+
Example: { "category": { "$in": ["electronics", "books"] } }
|
|
734
|
+
- $nin: Does not match any value in array
|
|
735
|
+
Example: { "category": { "$nin": ["electronics", "books"] } }
|
|
736
|
+
- $all: Match all values in array
|
|
737
|
+
Example: { "tags": { "$all": ["premium", "sale"] } }
|
|
738
|
+
|
|
739
|
+
Logical Operators:
|
|
740
|
+
- $and: Logical AND (implicit when using multiple conditions)
|
|
741
|
+
Example: { "$and": [{ "price": { "$gt": 100 } }, { "category": "electronics" }] }
|
|
742
|
+
- $or: Logical OR
|
|
743
|
+
Example: { "$or": [{ "price": { "$lt": 50 } }, { "category": "books" }] }
|
|
744
|
+
- $not: Logical NOT
|
|
745
|
+
Example: { "$not": { "category": "electronics" } }
|
|
746
|
+
|
|
747
|
+
Element Operators:
|
|
748
|
+
- $exists: Check if field exists
|
|
749
|
+
Example: { "rating": { "$exists": true } }
|
|
750
|
+
|
|
751
|
+
Regex Operator:
|
|
752
|
+
- $regex: Match using a regular expression (ECMAScript syntax)
|
|
753
|
+
Example: { "name": { "$regex": "^Sam.*son$" } }
|
|
754
|
+
Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.
|
|
755
|
+
|
|
756
|
+
Restrictions:
|
|
757
|
+
- Nested fields are supported using dot notation (e.g., "address.city").
|
|
758
|
+
- Multiple conditions on the same field are supported (e.g., { "price": { "$gte": 100, "$lte": 1000 } }).
|
|
759
|
+
- Only logical operators ($and, $or, $not) can be used at the top level.
|
|
760
|
+
- All other operators must be used within a field condition.
|
|
761
|
+
Valid: { "field": { "$gt": 100 } }
|
|
762
|
+
Valid: { "$and": [...] }
|
|
763
|
+
Invalid: { "$gt": 100 }
|
|
764
|
+
- Logical operators must contain field conditions, not direct operators.
|
|
765
|
+
Valid: { "$and": [{ "field": { "$gt": 100 } }] }
|
|
766
|
+
Invalid: { "$and": [{ "$gt": 100 }] }
|
|
767
|
+
- $not operator:
|
|
768
|
+
- Must be an object
|
|
769
|
+
- Cannot be empty
|
|
770
|
+
- Can be used at field level or top level
|
|
771
|
+
- Valid: { "$not": { "field": "value" } }
|
|
772
|
+
- Valid: { "field": { "$not": { "$eq": "value" } } }
|
|
773
|
+
- Array operators work on array fields only.
|
|
774
|
+
- Empty arrays in conditions are handled gracefully.
|
|
775
|
+
- Regex queries are case-sensitive by default; use patterns accordingly.
|
|
776
|
+
|
|
777
|
+
Example Complex Query:
|
|
778
|
+
{
|
|
779
|
+
"$and": [
|
|
780
|
+
{ "category": { "$in": ["electronics", "computers"] } },
|
|
781
|
+
{ "price": { "$gte": 100, "$lte": 1000 } },
|
|
782
|
+
{ "tags": { "$all": ["premium"] } },
|
|
783
|
+
{ "rating": { "$exists": true, "$gt": 4 } },
|
|
784
|
+
{ "$or": [
|
|
785
|
+
{ "stock": { "$gt": 0 } },
|
|
786
|
+
{ "preorder": true }
|
|
787
|
+
]},
|
|
788
|
+
{ "name": { "$regex": "^Sam.*son$" } }
|
|
789
|
+
]
|
|
790
|
+
}`;
|
|
791
|
+
//#endregion
|
|
792
|
+
exports.OPENSEARCH_PROMPT = OPENSEARCH_PROMPT;
|
|
708
793
|
exports.OpenSearchVector = OpenSearchVector;
|
|
709
794
|
|
|
710
795
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["BaseFilterTranslator","MastraVector","OpenSearchClient","MastraError","ErrorDomain","ErrorCategory"],"sources":["../src/vector/filter.ts","../src/vector/index.ts"],"sourcesContent":["import type {\n BlacklistedRootOperators,\n LogicalOperatorValueMap,\n OperatorSupport,\n OperatorValueMap,\n QueryOperator,\n VectorFilter,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\n\ntype OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;\n\ntype OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';\n\nexport type OpenSearchVectorFilter = VectorFilter<\n keyof OpenSearchOperatorValueMap,\n OpenSearchOperatorValueMap,\n OpenSearchLogicalOperatorValueMap,\n OpenSearchBlacklisted\n>;\n/**\n * Translator for OpenSearch filter queries.\n * Maintains OpenSearch-compatible syntax while ensuring proper validation\n * and normalization of values.\n */\nexport class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or', '$not'],\n array: ['$in', '$nin', '$all'],\n regex: ['$regex'],\n custom: [],\n };\n }\n\n translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter {\n if (this.isEmpty(filter)) return undefined;\n this.validateFilter(filter);\n return this.translateNode(filter);\n }\n\n private translateNode(node: OpenSearchVectorFilter): any {\n // Handle primitive values and arrays\n if (this.isPrimitive(node) || Array.isArray(node)) {\n return node;\n }\n\n const entries = Object.entries(node as Record<string, any>);\n\n // Extract logical operators and field conditions\n const logicalOperators: [string, any][] = [];\n const fieldConditions: [string, any][] = [];\n\n entries.forEach(([key, value]) => {\n if (this.isLogicalOperator(key)) {\n logicalOperators.push([key, value]);\n } else {\n fieldConditions.push([key, value]);\n }\n });\n\n // If we have a single logical operator\n if (logicalOperators.length === 1 && fieldConditions.length === 0) {\n const [operator, value] = logicalOperators[0] as [QueryOperator, any];\n if (!Array.isArray(value) && typeof value !== 'object') {\n throw new Error(`Invalid logical operator structure: ${operator} must have an array or object value`);\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // Process field conditions\n const fieldConditionQueries = fieldConditions.map(([key, value]) => {\n // Handle nested objects\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Check if the object contains operators\n const hasOperators = Object.keys(value).some(k => this.isOperator(k));\n\n // Use a more direct approach based on whether operators are present\n const nestedField = `metadata.${key}`;\n return hasOperators\n ? this.translateFieldConditions(nestedField, value)\n : this.translateNestedObject(nestedField, value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { terms: { [fieldWithKeyword]: value } };\n }\n\n // Handle simple field equality\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { term: { [fieldWithKeyword]: value } };\n });\n\n // Handle case with both logical operators and field conditions or multiple logical operators\n if (logicalOperators.length > 0) {\n const logicalConditions = logicalOperators.map(([operator, value]) =>\n this.translateOperator(operator as QueryOperator, value),\n );\n\n return {\n bool: {\n must: [...logicalConditions, ...fieldConditionQueries],\n },\n };\n }\n\n // If we only have field conditions\n if (fieldConditionQueries.length > 1) {\n return {\n bool: {\n must: fieldConditionQueries,\n },\n };\n }\n\n // If we have only one field condition\n if (fieldConditionQueries.length === 1) {\n return fieldConditionQueries[0];\n }\n\n // If we have no conditions (e.g., only empty $and arrays)\n return { match_all: {} };\n }\n\n /**\n * Handles translation of nested objects with dot notation fields\n */\n private translateNestedObject(field: string, value: Record<string, any>): any {\n const conditions = Object.entries(value).map(([subField, subValue]) => {\n const fullField = `${field}.${subField}`;\n\n // Check if this is an operator in a nested field\n if (this.isOperator(subField)) {\n return this.translateOperator(subField as QueryOperator, subValue, field);\n }\n\n if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {\n // Check if the nested object contains operators\n const hasOperators = Object.keys(subValue).some(k => this.isOperator(k));\n if (hasOperators) {\n return this.translateFieldConditions(fullField, subValue);\n }\n return this.translateNestedObject(fullField, subValue);\n }\n const fieldWithKeyword = this.addKeywordIfNeeded(fullField, subValue);\n return { term: { [fieldWithKeyword]: subValue } };\n });\n\n return {\n bool: {\n must: conditions,\n },\n };\n }\n\n private translateLogicalOperator(operator: QueryOperator, value: any): any {\n const conditions = Array.isArray(value) ? value.map(item => this.translateNode(item)) : [this.translateNode(value)];\n switch (operator) {\n case '$and':\n // For empty $and, return a query that matches everything\n if (Array.isArray(value) && value.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must: conditions,\n },\n };\n case '$or':\n // For empty $or, return a query that matches nothing\n if (Array.isArray(value) && value.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n should: conditions,\n },\n };\n case '$not':\n return {\n bool: {\n must_not: conditions,\n },\n };\n default:\n return value;\n }\n }\n\n private translateFieldOperator(field: string, operator: QueryOperator, value: any): any {\n // Handle basic comparison operators\n if (this.isBasicOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$eq':\n // Handle null equality: field does not exist or is null\n if (value === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n return { term: { [fieldWithKeyword]: normalizedValue } };\n case '$ne':\n // Handle null inequality: field exists (i.e., is not null)\n if (value === null) {\n return { exists: { field } };\n }\n return {\n bool: {\n must_not: [{ term: { [fieldWithKeyword]: normalizedValue } }],\n },\n };\n default:\n return { term: { [fieldWithKeyword]: normalizedValue } };\n }\n }\n\n // Handle numeric operators\n if (this.isNumericOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const rangeOp = operator.replace('$', '');\n return { range: { [field]: { [rangeOp]: normalizedValue } } };\n }\n\n // Handle array operators\n if (this.isArrayOperator(operator)) {\n if (!Array.isArray(value)) {\n throw new Error(`Invalid array operator value: ${operator} requires an array value`);\n }\n const normalizedValues = this.normalizeArrayValues(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$in':\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n case '$nin':\n // For empty arrays, return a query that matches everything\n if (normalizedValues.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must_not: [{ terms: { [fieldWithKeyword]: normalizedValues } }],\n },\n };\n case '$all':\n // For empty arrays, return a query that will match nothing\n if (normalizedValues.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n must: normalizedValues.map(v => ({ term: { [fieldWithKeyword]: v } })),\n },\n };\n default:\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n }\n }\n\n // Handle element operators\n if (this.isElementOperator(operator)) {\n switch (operator) {\n case '$exists':\n return value ? { exists: { field } } : { bool: { must_not: [{ exists: { field } }] } };\n default:\n return { exists: { field } };\n }\n }\n\n // Handle regex operators\n if (this.isRegexOperator(operator)) {\n return this.translateRegexOperator(field, value);\n }\n\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n return { term: { [fieldWithKeyword]: value } };\n }\n\n /**\n * Translates regex patterns to OpenSearch query syntax\n */\n private translateRegexOperator(field: string, value: any): any {\n // Convert value to string if it's not already\n const regexValue = typeof value === 'string' ? value : value.toString();\n\n // Check for problematic patterns (like newlines, etc.)\n if (regexValue.includes('\\n') || regexValue.includes('\\r')) {\n // For patterns with newlines, use a simpler approach\n // OpenSearch doesn't support dotall flag like JavaScript\n return { match: { [field]: value } };\n }\n\n // Process regex pattern to handle anchors properly\n let processedRegex = regexValue;\n const hasStartAnchor = regexValue.startsWith('^');\n const hasEndAnchor = regexValue.endsWith('$');\n\n // If we have anchors, use wildcard query for better handling\n if (hasStartAnchor || hasEndAnchor) {\n // Remove anchors\n if (hasStartAnchor) {\n processedRegex = processedRegex.substring(1);\n }\n if (hasEndAnchor) {\n processedRegex = processedRegex.substring(0, processedRegex.length - 1);\n }\n\n // Create wildcard pattern\n let wildcardPattern = processedRegex;\n if (!hasStartAnchor) {\n wildcardPattern = '*' + wildcardPattern;\n }\n if (!hasEndAnchor) {\n wildcardPattern = wildcardPattern + '*';\n }\n\n return { wildcard: { [field]: wildcardPattern } };\n }\n\n // Use regexp for other regex patterns\n // Escape any backslashes to prevent OpenSearch from misinterpreting them\n const escapedRegex = regexValue.replace(/\\\\/g, '\\\\\\\\');\n return { regexp: { [field]: escapedRegex } };\n }\n\n private addKeywordIfNeeded(field: string, value: any): string {\n // Add .keyword suffix for string fields\n if (typeof value === 'string') {\n return `${field}.keyword`;\n }\n // Add .keyword suffix for string array fields\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n return `${field}.keyword`;\n }\n return field;\n }\n\n /**\n * Helper method to handle special cases for the $not operator\n */\n private handleNotOperatorSpecialCases(value: any, field: string): any | null {\n // For \"not null\", we need to use exists query\n if (value === null) {\n return { exists: { field } };\n }\n\n if (typeof value === 'object' && value !== null) {\n // For \"not {$eq: null}\", we need to use exists query\n if ('$eq' in value && value.$eq === null) {\n return { exists: { field } };\n }\n\n // For \"not {$ne: null}\", we need to use must_not exists query\n if ('$ne' in value && value.$ne === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n }\n\n return null; // No special case applies\n }\n\n private translateOperator(operator: QueryOperator, value: any, field?: string): any {\n // Check if this is a valid operator\n if (!this.isOperator(operator)) {\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n // Special case for $not with null or $eq: null\n if (operator === '$not' && field) {\n const specialCaseResult = this.handleNotOperatorSpecialCases(value, field);\n if (specialCaseResult) {\n return specialCaseResult;\n }\n }\n\n // Handle logical operators\n if (this.isLogicalOperator(operator)) {\n // For $not operator with field context and nested operators, handle specially\n if (operator === '$not' && field && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const entries = Object.entries(value);\n\n // Handle multiple operators in $not\n if (entries.length > 0) {\n // If all entries are operators, handle them as a single condition\n if (entries.every(([op]) => this.isOperator(op))) {\n const translatedCondition = this.translateFieldConditions(field, value);\n return {\n bool: {\n must_not: [translatedCondition],\n },\n };\n }\n\n // Handle single nested operator\n if (entries.length === 1 && entries[0] && this.isOperator(entries[0][0])) {\n const [nestedOp, nestedVal] = entries[0] as [QueryOperator, any];\n const translatedNested = this.translateFieldOperator(field, nestedOp, nestedVal);\n return {\n bool: {\n must_not: [translatedNested],\n },\n };\n }\n }\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // If a field is provided, use translateFieldOperator for more specific translation\n if (field) {\n return this.translateFieldOperator(field, operator, value);\n }\n\n // For non-logical operators without a field context, just return the value\n // The actual translation happens in translateFieldConditions where we have the field context\n return value;\n }\n\n /**\n * Translates field conditions to OpenSearch query syntax\n * Handles special cases like range queries and multiple operators\n */\n private translateFieldConditions(field: string, conditions: Record<string, any>): any {\n // Special case: Optimize multiple numeric operators into a single range query\n if (this.canOptimizeToRangeQuery(conditions)) {\n return this.createRangeQuery(field, conditions);\n }\n\n // Handle all other operators consistently\n const queryConditions: any[] = [];\n Object.entries(conditions).forEach(([operator, value]) => {\n if (this.isOperator(operator)) {\n queryConditions.push(this.translateOperator(operator as QueryOperator, value, field));\n } else {\n // Handle non-operator keys (should not happen in normal usage)\n const fieldWithKeyword = this.addKeywordIfNeeded(`${field}.${operator}`, value);\n queryConditions.push({ term: { [fieldWithKeyword]: value } });\n }\n });\n\n // Return single condition without wrapping\n if (queryConditions.length === 1) {\n return queryConditions[0];\n }\n\n // Combine multiple conditions with AND logic\n return {\n bool: {\n must: queryConditions,\n },\n };\n }\n\n /**\n * Checks if conditions can be optimized to a range query\n */\n private canOptimizeToRangeQuery(conditions: Record<string, any>): boolean {\n return Object.keys(conditions).every(op => this.isNumericOperator(op)) && Object.keys(conditions).length > 0;\n }\n\n /**\n * Creates a range query from numeric operators\n */\n private createRangeQuery(field: string, conditions: Record<string, any>): any {\n const rangeParams = Object.fromEntries(\n Object.entries(conditions).map(([op, val]) => [op.replace('$', ''), this.normalizeComparisonValue(val)]),\n );\n\n return { range: { [field]: rangeParams } };\n }\n}\n","import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { MastraVector, validateUpsert, validateTopK } from '@mastra/core/vector';\nimport { Client as OpenSearchClient } from '@opensearch-project/opensearch';\nimport type { ClientOptions } from '@opensearch-project/opensearch';\nimport { OpenSearchFilterTranslator } from './filter';\nimport type { OpenSearchVectorFilter } from './filter';\n\n/**\n * Configuration for OpenSearchVector.\n *\n * Extends the OpenSearch ClientOptions with a required id.\n * All OpenSearch client options are supported (node, auth, ssl, compression, etc.).\n *\n * @example\n * ```typescript\n * // Simple URL config\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'http://localhost:9200',\n * });\n *\n * // With authentication\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'https://my-opensearch-cluster.com',\n * auth: { username: 'admin', password: 'secret' },\n * ssl: { rejectUnauthorized: false },\n * });\n * ```\n */\nexport type OpenSearchVectorConfig = ClientOptions & { id: string };\n\nconst METRIC_MAPPING = {\n cosine: 'cosinesimil',\n euclidean: 'l2',\n dotproduct: 'innerproduct',\n} as const;\n\nconst REVERSE_METRIC_MAPPING = {\n cosinesimil: 'cosine',\n l2: 'euclidean',\n innerproduct: 'dotproduct',\n} as const;\n\ntype OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;\n\nexport class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {\n private client: OpenSearchClient;\n\n /**\n * Creates a new OpenSearchVector client.\n *\n * @param config - OpenSearch client configuration options plus a required id.\n * @see OpenSearchVectorConfig for all available options.\n */\n constructor({ id, ...clientOptions }: OpenSearchVectorConfig) {\n super({ id });\n this.client = new OpenSearchClient(clientOptions);\n }\n\n /**\n * Creates a new collection with the specified configuration.\n *\n * @param {string} indexName - The name of the collection to create.\n * @param {number} dimension - The dimension of the vectors to be stored in the collection.\n * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.\n * @returns {Promise<void>} A promise that resolves when the collection is created.\n */\n async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {\n if (!Number.isInteger(dimension) || dimension <= 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Dimension must be a positive integer',\n details: { indexName, dimension },\n });\n }\n\n try {\n await this.client.indices.create({\n index: indexName,\n body: {\n settings: { index: { knn: true } },\n mappings: {\n properties: {\n metadata: { type: 'object' },\n id: { type: 'keyword' },\n embedding: {\n type: 'knn_vector',\n dimension: dimension,\n method: {\n name: 'hnsw',\n space_type: METRIC_MAPPING[metric],\n engine: 'faiss',\n parameters: { ef_construction: 128, m: 16 },\n },\n },\n },\n },\n },\n });\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n // Fetch collection info and check dimension\n await this.validateExistingIndex(indexName, dimension, metric);\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n }\n\n /**\n * Lists all indexes.\n *\n * @returns {Promise<string[]>} A promise that resolves to an array of indexes.\n */\n async listIndexes(): Promise<string[]> {\n try {\n const response = await this.client.cat.indices({ format: 'json' });\n const indexes = response.body\n .map((record: { index?: string }) => record.index)\n .filter((index: string | undefined) => index !== undefined);\n\n return indexes;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'LIST_INDEXES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n const { body: indexInfo } = await this.client.indices.get({ index: indexName });\n const mappings = indexInfo[indexName]?.mappings;\n const embedding: any = mappings?.properties?.embedding;\n const spaceType = embedding.method.space_type as keyof typeof REVERSE_METRIC_MAPPING;\n\n const { body: countInfo } = await this.client.count({ index: indexName });\n\n return {\n dimension: Number(embedding.dimension),\n count: Number(countInfo.count),\n metric: REVERSE_METRIC_MAPPING[spaceType],\n };\n }\n\n /**\n * Deletes the specified index.\n *\n * @param {string} indexName - The name of the index to delete.\n * @returns {Promise<void>} A promise that resolves when the index is deleted.\n */\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n await this.client.indices.delete({ index: indexName });\n } catch (error) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n }\n }\n\n /**\n * Inserts or updates vectors in the specified collection.\n *\n * @param {string} indexName - The name of the collection to upsert into.\n * @param {number[][]} vectors - An array of vectors to upsert.\n * @param {Record<string, any>[]} [metadata] - An optional array of metadata objects corresponding to each vector.\n * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.\n * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.\n */\n async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {\n // Validate input parameters and vector values\n validateUpsert('OPENSEARCH', vectors, metadata, ids, true);\n\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const operations = [];\n\n try {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions(vectors, indexInfo.dimension);\n\n for (let i = 0; i < vectors.length; i++) {\n const operation = {\n index: {\n _index: indexName,\n _id: vectorIds[i],\n },\n };\n\n const document = {\n id: vectorIds[i],\n embedding: vectors[i],\n metadata: metadata[i] || {},\n };\n\n operations.push(operation);\n operations.push(document);\n }\n\n if (operations.length > 0) {\n await this.client.bulk({ body: operations, refresh: true });\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, vectorCount: vectors?.length || 0 },\n },\n error,\n );\n }\n }\n\n /**\n * Queries the specified collection using a vector and optional filter.\n *\n * @param {string} indexName - The name of the collection to query.\n * @param {number[]} queryVector - The vector to query with.\n * @param {number} [topK] - The maximum number of results to return.\n * @param {Record<string, any>} [filter] - An optional filter to apply to the query. For more on filters in OpenSearch, see the filtering reference: https://opensearch.org/docs/latest/query-dsl/\n * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.\n * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.\n */\n async query({\n indexName,\n queryVector,\n filter,\n topK = 10,\n includeVector = false,\n }: OpenSearchVectorParams): Promise<QueryResult[]> {\n if (!queryVector) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'MISSING_VECTOR'),\n text: 'queryVector is required for OpenSearch queries. Metadata-only queries are not supported by this vector store.',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n });\n }\n\n // Validate topK parameter\n validateTopK('OPENSEARCH', topK);\n\n try {\n const translatedFilter = this.transformFilter(filter);\n\n const response = await this.client.search({\n index: indexName,\n body: {\n query: {\n bool: {\n must: { knn: { embedding: { vector: queryVector, k: topK } } },\n filter: translatedFilter ? [translatedFilter] : [],\n },\n },\n _source: ['id', 'metadata', 'embedding'],\n },\n });\n\n const results = response.body.hits.hits.map((hit: any) => {\n const source = hit._source || {};\n return {\n id: String(source.id || ''),\n score: typeof hit._score === 'number' ? hit._score : 0,\n metadata: source.metadata || {},\n ...(includeVector && { vector: source.embedding as number[] }),\n };\n });\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, topK },\n },\n error,\n );\n }\n }\n\n /**\n * Validates the dimensions of the vectors.\n *\n * @param {number[][]} vectors - The vectors to validate.\n * @param {number} dimension - The dimension of the vectors.\n * @returns {void}\n */\n private validateVectorDimensions(vectors: number[][], dimension: number) {\n if (vectors.some(vector => vector.length !== dimension)) {\n throw new Error('Vector dimension does not match index dimension');\n }\n }\n\n /**\n * Transforms the filter to the OpenSearch DSL.\n *\n * @param {OpenSearchVectorFilter} filter - The filter to transform.\n * @returns {Record<string, any>} The transformed filter.\n */\n private transformFilter(filter?: OpenSearchVectorFilter): any {\n const translator = new OpenSearchFilterTranslator();\n return translator.translate(filter);\n }\n\n /**\n * Updates vectors by ID or filter with the provided vector and/or metadata.\n * @param params - Parameters containing either id or filter for targeting vectors to update\n * @param params.indexName - The name of the index containing the vector(s).\n * @param params.id - The ID of a single vector to update (mutually exclusive with filter).\n * @param params.filter - A filter to match multiple vectors to update (mutually exclusive with id).\n * @param params.update - An object containing the vector and/or metadata to update.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector(params: UpdateVectorParams<OpenSearchVectorFilter>): Promise<void> {\n const { indexName, update } = params;\n\n // Validate mutually exclusive parameters\n if ('id' in params && 'filter' in params && params.id && params.filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'id and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!update.vector && !update.metadata) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_UPDATES'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'No updates provided',\n details: { indexName },\n });\n }\n\n // Validate empty filter\n if ('filter' in params && params.filter && Object.keys(params.filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot update with empty filter',\n details: { indexName },\n });\n }\n\n // Type-narrowing: check if updating by id or by filter\n if ('id' in params && params.id) {\n // Update by ID\n await this.updateVectorById(indexName, params.id, update);\n } else if ('filter' in params && params.filter) {\n // Update by filter\n await this.updateVectorsByFilter(indexName, params.filter, update);\n } else {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either id or filter must be provided',\n details: { indexName },\n });\n }\n }\n\n /**\n * Updates a single vector by its ID.\n */\n private async updateVectorById(\n indexName: string,\n id: string,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n let existingDoc;\n try {\n // First get the current document to merge with updates\n const { body } = await this.client\n .get({\n index: indexName,\n id: id,\n })\n .catch(() => {\n throw new Error(`Document with ID ${id} not found in index ${indexName}`);\n });\n\n if (!body || !body._source) {\n throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);\n }\n existingDoc = body;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n\n const source = existingDoc._source;\n const updatedDoc: Record<string, any> = {\n id: source?.id || id,\n };\n\n try {\n // Update vector if provided\n if (update.vector) {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions([update.vector], indexInfo.dimension);\n\n updatedDoc.embedding = update.vector;\n } else if (source?.embedding) {\n updatedDoc.embedding = source.embedding;\n }\n\n // Update metadata if provided\n if (update.metadata) {\n updatedDoc.metadata = update.metadata;\n } else {\n updatedDoc.metadata = source?.metadata || {};\n }\n\n // Update the document\n await this.client.index({\n index: indexName,\n id: id,\n body: updatedDoc,\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Updates multiple vectors matching a filter.\n */\n private async updateVectorsByFilter(\n indexName: string,\n filter: OpenSearchVectorFilter,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n try {\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n // Build the update script\n const scriptSource: string[] = [];\n const scriptParams: Record<string, any> = {};\n\n if (update.vector) {\n scriptSource.push('ctx._source.embedding = params.embedding');\n scriptParams.embedding = update.vector;\n }\n\n if (update.metadata) {\n scriptSource.push('ctx._source.metadata = params.metadata');\n scriptParams.metadata = update.metadata;\n }\n\n // Use update_by_query to update all matching documents\n await this.client.updateByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n script: {\n source: scriptSource.join('; '),\n params: scriptParams,\n lang: 'painless',\n },\n },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR_BY_FILTER', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n filter: JSON.stringify(filter),\n },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n await this.client.delete({\n index: indexName,\n id: id,\n refresh: true,\n });\n } catch (error: unknown) {\n // Don't throw error if document doesn't exist (404)\n if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<OpenSearchVectorFilter>): Promise<void> {\n // Validate mutually exclusive parameters\n if (ids && filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'ids and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!ids && !filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either filter or ids must be provided',\n details: { indexName },\n });\n }\n\n // Validate non-empty arrays and objects\n if (ids && ids.length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_IDS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty ids array',\n details: { indexName },\n });\n }\n\n if (filter && Object.keys(filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty filter',\n details: { indexName },\n });\n }\n\n try {\n if (ids) {\n // Delete by IDs using bulk API\n const bulkBody = ids.flatMap(id => [{ delete: { _index: indexName, _id: id } }]);\n\n await this.client.bulk({\n body: bulkBody,\n refresh: true,\n });\n } else if (filter) {\n // Delete by filter using delete_by_query\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n await this.client.deleteByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n },\n refresh: true,\n });\n }\n } catch (error) {\n if (error instanceof MastraError) throw error;\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(filter && { filter: JSON.stringify(filter) }),\n ...(ids && { idsCount: ids.length }),\n },\n },\n error,\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["BaseFilterTranslator","MastraVector","OpenSearchClient","MastraError","ErrorDomain","ErrorCategory"],"sources":["../src/vector/filter.ts","../src/vector/index.ts","../src/vector/prompt.ts"],"sourcesContent":["import type {\n BlacklistedRootOperators,\n LogicalOperatorValueMap,\n OperatorSupport,\n OperatorValueMap,\n QueryOperator,\n VectorFilter,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\n\ntype OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;\n\ntype OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';\n\nexport type OpenSearchVectorFilter = VectorFilter<\n keyof OpenSearchOperatorValueMap,\n OpenSearchOperatorValueMap,\n OpenSearchLogicalOperatorValueMap,\n OpenSearchBlacklisted\n>;\n/**\n * Translator for OpenSearch filter queries.\n * Maintains OpenSearch-compatible syntax while ensuring proper validation\n * and normalization of values.\n */\nexport class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or', '$not'],\n array: ['$in', '$nin', '$all'],\n regex: ['$regex'],\n custom: [],\n };\n }\n\n translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter {\n if (this.isEmpty(filter)) return undefined;\n this.validateFilter(filter);\n return this.translateNode(filter);\n }\n\n private translateNode(node: OpenSearchVectorFilter): any {\n // Handle primitive values and arrays\n if (this.isPrimitive(node) || Array.isArray(node)) {\n return node;\n }\n\n const entries = Object.entries(node as Record<string, any>);\n\n // Extract logical operators and field conditions\n const logicalOperators: [string, any][] = [];\n const fieldConditions: [string, any][] = [];\n\n entries.forEach(([key, value]) => {\n if (this.isLogicalOperator(key)) {\n logicalOperators.push([key, value]);\n } else {\n fieldConditions.push([key, value]);\n }\n });\n\n // If we have a single logical operator\n if (logicalOperators.length === 1 && fieldConditions.length === 0) {\n const [operator, value] = logicalOperators[0] as [QueryOperator, any];\n if (!Array.isArray(value) && typeof value !== 'object') {\n throw new Error(`Invalid logical operator structure: ${operator} must have an array or object value`);\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // Process field conditions\n const fieldConditionQueries = fieldConditions.map(([key, value]) => {\n // Handle nested objects\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Check if the object contains operators\n const hasOperators = Object.keys(value).some(k => this.isOperator(k));\n\n // Use a more direct approach based on whether operators are present\n const nestedField = `metadata.${key}`;\n return hasOperators\n ? this.translateFieldConditions(nestedField, value)\n : this.translateNestedObject(nestedField, value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { terms: { [fieldWithKeyword]: value } };\n }\n\n // Handle simple field equality\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { term: { [fieldWithKeyword]: value } };\n });\n\n // Handle case with both logical operators and field conditions or multiple logical operators\n if (logicalOperators.length > 0) {\n const logicalConditions = logicalOperators.map(([operator, value]) =>\n this.translateOperator(operator as QueryOperator, value),\n );\n\n return {\n bool: {\n must: [...logicalConditions, ...fieldConditionQueries],\n },\n };\n }\n\n // If we only have field conditions\n if (fieldConditionQueries.length > 1) {\n return {\n bool: {\n must: fieldConditionQueries,\n },\n };\n }\n\n // If we have only one field condition\n if (fieldConditionQueries.length === 1) {\n return fieldConditionQueries[0];\n }\n\n // If we have no conditions (e.g., only empty $and arrays)\n return { match_all: {} };\n }\n\n /**\n * Handles translation of nested objects with dot notation fields\n */\n private translateNestedObject(field: string, value: Record<string, any>): any {\n const conditions = Object.entries(value).map(([subField, subValue]) => {\n const fullField = `${field}.${subField}`;\n\n // Check if this is an operator in a nested field\n if (this.isOperator(subField)) {\n return this.translateOperator(subField as QueryOperator, subValue, field);\n }\n\n if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {\n // Check if the nested object contains operators\n const hasOperators = Object.keys(subValue).some(k => this.isOperator(k));\n if (hasOperators) {\n return this.translateFieldConditions(fullField, subValue);\n }\n return this.translateNestedObject(fullField, subValue);\n }\n const fieldWithKeyword = this.addKeywordIfNeeded(fullField, subValue);\n return { term: { [fieldWithKeyword]: subValue } };\n });\n\n return {\n bool: {\n must: conditions,\n },\n };\n }\n\n private translateLogicalOperator(operator: QueryOperator, value: any): any {\n const conditions = Array.isArray(value) ? value.map(item => this.translateNode(item)) : [this.translateNode(value)];\n switch (operator) {\n case '$and':\n // For empty $and, return a query that matches everything\n if (Array.isArray(value) && value.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must: conditions,\n },\n };\n case '$or':\n // For empty $or, return a query that matches nothing\n if (Array.isArray(value) && value.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n should: conditions,\n },\n };\n case '$not':\n return {\n bool: {\n must_not: conditions,\n },\n };\n default:\n return value;\n }\n }\n\n private translateFieldOperator(field: string, operator: QueryOperator, value: any): any {\n // Handle basic comparison operators\n if (this.isBasicOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$eq':\n // Handle null equality: field does not exist or is null\n if (value === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n return { term: { [fieldWithKeyword]: normalizedValue } };\n case '$ne':\n // Handle null inequality: field exists (i.e., is not null)\n if (value === null) {\n return { exists: { field } };\n }\n return {\n bool: {\n must_not: [{ term: { [fieldWithKeyword]: normalizedValue } }],\n },\n };\n default:\n return { term: { [fieldWithKeyword]: normalizedValue } };\n }\n }\n\n // Handle numeric operators\n if (this.isNumericOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const rangeOp = operator.replace('$', '');\n return { range: { [field]: { [rangeOp]: normalizedValue } } };\n }\n\n // Handle array operators\n if (this.isArrayOperator(operator)) {\n if (!Array.isArray(value)) {\n throw new Error(`Invalid array operator value: ${operator} requires an array value`);\n }\n const normalizedValues = this.normalizeArrayValues(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$in':\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n case '$nin':\n // For empty arrays, return a query that matches everything\n if (normalizedValues.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must_not: [{ terms: { [fieldWithKeyword]: normalizedValues } }],\n },\n };\n case '$all':\n // For empty arrays, return a query that will match nothing\n if (normalizedValues.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n must: normalizedValues.map(v => ({ term: { [fieldWithKeyword]: v } })),\n },\n };\n default:\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n }\n }\n\n // Handle element operators\n if (this.isElementOperator(operator)) {\n switch (operator) {\n case '$exists':\n return value ? { exists: { field } } : { bool: { must_not: [{ exists: { field } }] } };\n default:\n return { exists: { field } };\n }\n }\n\n // Handle regex operators\n if (this.isRegexOperator(operator)) {\n return this.translateRegexOperator(field, value);\n }\n\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n return { term: { [fieldWithKeyword]: value } };\n }\n\n /**\n * Translates regex patterns to OpenSearch query syntax\n */\n private translateRegexOperator(field: string, value: any): any {\n // Convert value to string if it's not already\n const regexValue = typeof value === 'string' ? value : value.toString();\n\n // Check for problematic patterns (like newlines, etc.)\n if (regexValue.includes('\\n') || regexValue.includes('\\r')) {\n // For patterns with newlines, use a simpler approach\n // OpenSearch doesn't support dotall flag like JavaScript\n return { match: { [field]: value } };\n }\n\n // Process regex pattern to handle anchors properly\n let processedRegex = regexValue;\n const hasStartAnchor = regexValue.startsWith('^');\n const hasEndAnchor = regexValue.endsWith('$');\n\n // If we have anchors, use wildcard query for better handling\n if (hasStartAnchor || hasEndAnchor) {\n // Remove anchors\n if (hasStartAnchor) {\n processedRegex = processedRegex.substring(1);\n }\n if (hasEndAnchor) {\n processedRegex = processedRegex.substring(0, processedRegex.length - 1);\n }\n\n // Create wildcard pattern\n let wildcardPattern = processedRegex;\n if (!hasStartAnchor) {\n wildcardPattern = '*' + wildcardPattern;\n }\n if (!hasEndAnchor) {\n wildcardPattern = wildcardPattern + '*';\n }\n\n return { wildcard: { [field]: wildcardPattern } };\n }\n\n // Use regexp for other regex patterns\n // Escape any backslashes to prevent OpenSearch from misinterpreting them\n const escapedRegex = regexValue.replace(/\\\\/g, '\\\\\\\\');\n return { regexp: { [field]: escapedRegex } };\n }\n\n private addKeywordIfNeeded(field: string, value: any): string {\n // Add .keyword suffix for string fields\n if (typeof value === 'string') {\n return `${field}.keyword`;\n }\n // Add .keyword suffix for string array fields\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n return `${field}.keyword`;\n }\n return field;\n }\n\n /**\n * Helper method to handle special cases for the $not operator\n */\n private handleNotOperatorSpecialCases(value: any, field: string): any | null {\n // For \"not null\", we need to use exists query\n if (value === null) {\n return { exists: { field } };\n }\n\n if (typeof value === 'object' && value !== null) {\n // For \"not {$eq: null}\", we need to use exists query\n if ('$eq' in value && value.$eq === null) {\n return { exists: { field } };\n }\n\n // For \"not {$ne: null}\", we need to use must_not exists query\n if ('$ne' in value && value.$ne === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n }\n\n return null; // No special case applies\n }\n\n private translateOperator(operator: QueryOperator, value: any, field?: string): any {\n // Check if this is a valid operator\n if (!this.isOperator(operator)) {\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n // Special case for $not with null or $eq: null\n if (operator === '$not' && field) {\n const specialCaseResult = this.handleNotOperatorSpecialCases(value, field);\n if (specialCaseResult) {\n return specialCaseResult;\n }\n }\n\n // Handle logical operators\n if (this.isLogicalOperator(operator)) {\n // For $not operator with field context and nested operators, handle specially\n if (operator === '$not' && field && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const entries = Object.entries(value);\n\n // Handle multiple operators in $not\n if (entries.length > 0) {\n // If all entries are operators, handle them as a single condition\n if (entries.every(([op]) => this.isOperator(op))) {\n const translatedCondition = this.translateFieldConditions(field, value);\n return {\n bool: {\n must_not: [translatedCondition],\n },\n };\n }\n\n // Handle single nested operator\n if (entries.length === 1 && entries[0] && this.isOperator(entries[0][0])) {\n const [nestedOp, nestedVal] = entries[0] as [QueryOperator, any];\n const translatedNested = this.translateFieldOperator(field, nestedOp, nestedVal);\n return {\n bool: {\n must_not: [translatedNested],\n },\n };\n }\n }\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // If a field is provided, use translateFieldOperator for more specific translation\n if (field) {\n return this.translateFieldOperator(field, operator, value);\n }\n\n // For non-logical operators without a field context, just return the value\n // The actual translation happens in translateFieldConditions where we have the field context\n return value;\n }\n\n /**\n * Translates field conditions to OpenSearch query syntax\n * Handles special cases like range queries and multiple operators\n */\n private translateFieldConditions(field: string, conditions: Record<string, any>): any {\n // Special case: Optimize multiple numeric operators into a single range query\n if (this.canOptimizeToRangeQuery(conditions)) {\n return this.createRangeQuery(field, conditions);\n }\n\n // Handle all other operators consistently\n const queryConditions: any[] = [];\n Object.entries(conditions).forEach(([operator, value]) => {\n if (this.isOperator(operator)) {\n queryConditions.push(this.translateOperator(operator as QueryOperator, value, field));\n } else {\n // Handle non-operator keys (should not happen in normal usage)\n const fieldWithKeyword = this.addKeywordIfNeeded(`${field}.${operator}`, value);\n queryConditions.push({ term: { [fieldWithKeyword]: value } });\n }\n });\n\n // Return single condition without wrapping\n if (queryConditions.length === 1) {\n return queryConditions[0];\n }\n\n // Combine multiple conditions with AND logic\n return {\n bool: {\n must: queryConditions,\n },\n };\n }\n\n /**\n * Checks if conditions can be optimized to a range query\n */\n private canOptimizeToRangeQuery(conditions: Record<string, any>): boolean {\n return Object.keys(conditions).every(op => this.isNumericOperator(op)) && Object.keys(conditions).length > 0;\n }\n\n /**\n * Creates a range query from numeric operators\n */\n private createRangeQuery(field: string, conditions: Record<string, any>): any {\n const rangeParams = Object.fromEntries(\n Object.entries(conditions).map(([op, val]) => [op.replace('$', ''), this.normalizeComparisonValue(val)]),\n );\n\n return { range: { [field]: rangeParams } };\n }\n}\n","import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { MastraVector, validateUpsert, validateTopK } from '@mastra/core/vector';\nimport { Client as OpenSearchClient } from '@opensearch-project/opensearch';\nimport type { ClientOptions } from '@opensearch-project/opensearch';\nimport { OpenSearchFilterTranslator } from './filter';\nimport type { OpenSearchVectorFilter } from './filter';\n\n/**\n * Configuration for OpenSearchVector.\n *\n * Extends the OpenSearch ClientOptions with a required id.\n * All OpenSearch client options are supported (node, auth, ssl, compression, etc.).\n *\n * @example\n * ```typescript\n * // Simple URL config\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'http://localhost:9200',\n * });\n *\n * // With authentication\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'https://my-opensearch-cluster.com',\n * auth: { username: 'admin', password: 'secret' },\n * ssl: { rejectUnauthorized: false },\n * });\n * ```\n */\nexport type OpenSearchVectorConfig = ClientOptions & { id: string };\n\nconst METRIC_MAPPING = {\n cosine: 'cosinesimil',\n euclidean: 'l2',\n dotproduct: 'innerproduct',\n} as const;\n\nconst REVERSE_METRIC_MAPPING = {\n cosinesimil: 'cosine',\n l2: 'euclidean',\n innerproduct: 'dotproduct',\n} as const;\n\ntype OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;\n\nexport class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {\n private client: OpenSearchClient;\n\n /**\n * Creates a new OpenSearchVector client.\n *\n * @param config - OpenSearch client configuration options plus a required id.\n * @see OpenSearchVectorConfig for all available options.\n */\n constructor({ id, ...clientOptions }: OpenSearchVectorConfig) {\n super({ id });\n this.client = new OpenSearchClient(clientOptions);\n }\n\n /**\n * Creates a new collection with the specified configuration.\n *\n * @param {string} indexName - The name of the collection to create.\n * @param {number} dimension - The dimension of the vectors to be stored in the collection.\n * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.\n * @returns {Promise<void>} A promise that resolves when the collection is created.\n */\n async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {\n if (!Number.isInteger(dimension) || dimension <= 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Dimension must be a positive integer',\n details: { indexName, dimension },\n });\n }\n\n try {\n await this.client.indices.create({\n index: indexName,\n body: {\n settings: { index: { knn: true } },\n mappings: {\n properties: {\n metadata: { type: 'object' },\n id: { type: 'keyword' },\n embedding: {\n type: 'knn_vector',\n dimension: dimension,\n method: {\n name: 'hnsw',\n space_type: METRIC_MAPPING[metric],\n engine: 'faiss',\n parameters: { ef_construction: 128, m: 16 },\n },\n },\n },\n },\n },\n });\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n // Fetch collection info and check dimension\n await this.validateExistingIndex(indexName, dimension, metric);\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n }\n\n /**\n * Lists all indexes.\n *\n * @returns {Promise<string[]>} A promise that resolves to an array of indexes.\n */\n async listIndexes(): Promise<string[]> {\n try {\n const response = await this.client.cat.indices({ format: 'json' });\n const indexes = response.body\n .map((record: { index?: string }) => record.index)\n .filter((index: string | undefined) => index !== undefined);\n\n return indexes;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'LIST_INDEXES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n const { body: indexInfo } = await this.client.indices.get({ index: indexName });\n const mappings = indexInfo[indexName]?.mappings;\n const embedding: any = mappings?.properties?.embedding;\n const spaceType = embedding.method.space_type as keyof typeof REVERSE_METRIC_MAPPING;\n\n const { body: countInfo } = await this.client.count({ index: indexName });\n\n return {\n dimension: Number(embedding.dimension),\n count: Number(countInfo.count),\n metric: REVERSE_METRIC_MAPPING[spaceType],\n };\n }\n\n /**\n * Deletes the specified index.\n *\n * @param {string} indexName - The name of the index to delete.\n * @returns {Promise<void>} A promise that resolves when the index is deleted.\n */\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n await this.client.indices.delete({ index: indexName });\n } catch (error) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n }\n }\n\n /**\n * Inserts or updates vectors in the specified collection.\n *\n * @param {string} indexName - The name of the collection to upsert into.\n * @param {number[][]} vectors - An array of vectors to upsert.\n * @param {Record<string, any>[]} [metadata] - An optional array of metadata objects corresponding to each vector.\n * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.\n * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.\n */\n async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {\n // Validate input parameters and vector values\n validateUpsert('OPENSEARCH', vectors, metadata, ids, true);\n\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const operations = [];\n\n try {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions(vectors, indexInfo.dimension);\n\n for (let i = 0; i < vectors.length; i++) {\n const operation = {\n index: {\n _index: indexName,\n _id: vectorIds[i],\n },\n };\n\n const document = {\n id: vectorIds[i],\n embedding: vectors[i],\n metadata: metadata[i] || {},\n };\n\n operations.push(operation);\n operations.push(document);\n }\n\n if (operations.length > 0) {\n await this.client.bulk({ body: operations, refresh: true });\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, vectorCount: vectors?.length || 0 },\n },\n error,\n );\n }\n }\n\n /**\n * Queries the specified collection using a vector and optional filter.\n *\n * @param {string} indexName - The name of the collection to query.\n * @param {number[]} queryVector - The vector to query with.\n * @param {number} [topK] - The maximum number of results to return.\n * @param {Record<string, any>} [filter] - An optional filter to apply to the query. For more on filters in OpenSearch, see the filtering reference: https://opensearch.org/docs/latest/query-dsl/\n * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.\n * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.\n */\n async query({\n indexName,\n queryVector,\n filter,\n topK = 10,\n includeVector = false,\n }: OpenSearchVectorParams): Promise<QueryResult[]> {\n if (!queryVector) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'MISSING_VECTOR'),\n text: 'queryVector is required for OpenSearch queries. Metadata-only queries are not supported by this vector store.',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n });\n }\n\n // Validate topK parameter\n validateTopK('OPENSEARCH', topK);\n\n try {\n const translatedFilter = this.transformFilter(filter);\n\n const response = await this.client.search({\n index: indexName,\n body: {\n query: {\n bool: {\n must: { knn: { embedding: { vector: queryVector, k: topK } } },\n filter: translatedFilter ? [translatedFilter] : [],\n },\n },\n _source: ['id', 'metadata', 'embedding'],\n },\n });\n\n const results = response.body.hits.hits.map((hit: any) => {\n const source = hit._source || {};\n return {\n id: String(source.id || ''),\n score: typeof hit._score === 'number' ? hit._score : 0,\n metadata: source.metadata || {},\n ...(includeVector && { vector: source.embedding as number[] }),\n };\n });\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, topK },\n },\n error,\n );\n }\n }\n\n /**\n * Validates the dimensions of the vectors.\n *\n * @param {number[][]} vectors - The vectors to validate.\n * @param {number} dimension - The dimension of the vectors.\n * @returns {void}\n */\n private validateVectorDimensions(vectors: number[][], dimension: number) {\n if (vectors.some(vector => vector.length !== dimension)) {\n throw new Error('Vector dimension does not match index dimension');\n }\n }\n\n /**\n * Transforms the filter to the OpenSearch DSL.\n *\n * @param {OpenSearchVectorFilter} filter - The filter to transform.\n * @returns {Record<string, any>} The transformed filter.\n */\n private transformFilter(filter?: OpenSearchVectorFilter): any {\n const translator = new OpenSearchFilterTranslator();\n return translator.translate(filter);\n }\n\n /**\n * Updates vectors by ID or filter with the provided vector and/or metadata.\n * @param params - Parameters containing either id or filter for targeting vectors to update\n * @param params.indexName - The name of the index containing the vector(s).\n * @param params.id - The ID of a single vector to update (mutually exclusive with filter).\n * @param params.filter - A filter to match multiple vectors to update (mutually exclusive with id).\n * @param params.update - An object containing the vector and/or metadata to update.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector(params: UpdateVectorParams<OpenSearchVectorFilter>): Promise<void> {\n const { indexName, update } = params;\n\n // Validate mutually exclusive parameters\n if ('id' in params && 'filter' in params && params.id && params.filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'id and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!update.vector && !update.metadata) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_UPDATES'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'No updates provided',\n details: { indexName },\n });\n }\n\n // Validate empty filter\n if ('filter' in params && params.filter && Object.keys(params.filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot update with empty filter',\n details: { indexName },\n });\n }\n\n // Type-narrowing: check if updating by id or by filter\n if ('id' in params && params.id) {\n // Update by ID\n await this.updateVectorById(indexName, params.id, update);\n } else if ('filter' in params && params.filter) {\n // Update by filter\n await this.updateVectorsByFilter(indexName, params.filter, update);\n } else {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either id or filter must be provided',\n details: { indexName },\n });\n }\n }\n\n /**\n * Updates a single vector by its ID.\n */\n private async updateVectorById(\n indexName: string,\n id: string,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n let existingDoc;\n try {\n // First get the current document to merge with updates\n const { body } = await this.client\n .get({\n index: indexName,\n id: id,\n })\n .catch(() => {\n throw new Error(`Document with ID ${id} not found in index ${indexName}`);\n });\n\n if (!body || !body._source) {\n throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);\n }\n existingDoc = body;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n\n const source = existingDoc._source;\n const updatedDoc: Record<string, any> = {\n id: source?.id || id,\n };\n\n try {\n // Update vector if provided\n if (update.vector) {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions([update.vector], indexInfo.dimension);\n\n updatedDoc.embedding = update.vector;\n } else if (source?.embedding) {\n updatedDoc.embedding = source.embedding;\n }\n\n // Update metadata if provided\n if (update.metadata) {\n updatedDoc.metadata = update.metadata;\n } else {\n updatedDoc.metadata = source?.metadata || {};\n }\n\n // Update the document\n await this.client.index({\n index: indexName,\n id: id,\n body: updatedDoc,\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Updates multiple vectors matching a filter.\n */\n private async updateVectorsByFilter(\n indexName: string,\n filter: OpenSearchVectorFilter,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n try {\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n // Build the update script\n const scriptSource: string[] = [];\n const scriptParams: Record<string, any> = {};\n\n if (update.vector) {\n scriptSource.push('ctx._source.embedding = params.embedding');\n scriptParams.embedding = update.vector;\n }\n\n if (update.metadata) {\n scriptSource.push('ctx._source.metadata = params.metadata');\n scriptParams.metadata = update.metadata;\n }\n\n // Use update_by_query to update all matching documents\n await this.client.updateByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n script: {\n source: scriptSource.join('; '),\n params: scriptParams,\n lang: 'painless',\n },\n },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR_BY_FILTER', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n filter: JSON.stringify(filter),\n },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n await this.client.delete({\n index: indexName,\n id: id,\n refresh: true,\n });\n } catch (error: unknown) {\n // Don't throw error if document doesn't exist (404)\n if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<OpenSearchVectorFilter>): Promise<void> {\n // Validate mutually exclusive parameters\n if (ids && filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'ids and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!ids && !filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either filter or ids must be provided',\n details: { indexName },\n });\n }\n\n // Validate non-empty arrays and objects\n if (ids && ids.length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_IDS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty ids array',\n details: { indexName },\n });\n }\n\n if (filter && Object.keys(filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty filter',\n details: { indexName },\n });\n }\n\n try {\n if (ids) {\n // Delete by IDs using bulk API\n const bulkBody = ids.flatMap(id => [{ delete: { _index: indexName, _id: id } }]);\n\n await this.client.bulk({\n body: bulkBody,\n refresh: true,\n });\n } else if (filter) {\n // Delete by filter using delete_by_query\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n await this.client.deleteByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n },\n refresh: true,\n });\n }\n } catch (error) {\n if (error instanceof MastraError) throw error;\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(filter && { filter: JSON.stringify(filter) }),\n ...(ids && { idsCount: ids.length }),\n },\n },\n error,\n );\n }\n }\n}\n","/**\n * Vector store prompt for OpenSearch. This prompt details supported filter operators, syntax, and usage examples.\n * Use this as a guide for constructing valid filters for OpenSearch vector queries in Mastra.\n */\nexport const OPENSEARCH_PROMPT = `When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.\nImportant: Do not explain how to construct the filter—use the specified operators and fields to search the content and return relevant results.\nIf a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.\n\nBasic Comparison Operators:\n- $eq: Exact match (default for field: value)\n Example: { \"category\": \"electronics\" }\n- $ne: Not equal\n Example: { \"category\": { \"$ne\": \"electronics\" } }\n- $gt: Greater than\n Example: { \"price\": { \"$gt\": 100 } }\n- $gte: Greater than or equal\n Example: { \"price\": { \"$gte\": 100 } }\n- $lt: Less than\n Example: { \"price\": { \"$lt\": 100 } }\n- $lte: Less than or equal\n Example: { \"price\": { \"$lte\": 100 } }\n\nArray Operators:\n- $in: Match any value in array\n Example: { \"category\": { \"$in\": [\"electronics\", \"books\"] } }\n- $nin: Does not match any value in array\n Example: { \"category\": { \"$nin\": [\"electronics\", \"books\"] } }\n- $all: Match all values in array\n Example: { \"tags\": { \"$all\": [\"premium\", \"sale\"] } }\n\nLogical Operators:\n- $and: Logical AND (implicit when using multiple conditions)\n Example: { \"$and\": [{ \"price\": { \"$gt\": 100 } }, { \"category\": \"electronics\" }] }\n- $or: Logical OR\n Example: { \"$or\": [{ \"price\": { \"$lt\": 50 } }, { \"category\": \"books\" }] }\n- $not: Logical NOT\n Example: { \"$not\": { \"category\": \"electronics\" } }\n\nElement Operators:\n- $exists: Check if field exists\n Example: { \"rating\": { \"$exists\": true } }\n\nRegex Operator:\n- $regex: Match using a regular expression (ECMAScript syntax)\n Example: { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.\n\nRestrictions:\n- Nested fields are supported using dot notation (e.g., \"address.city\").\n- Multiple conditions on the same field are supported (e.g., { \"price\": { \"$gte\": 100, \"$lte\": 1000 } }).\n- Only logical operators ($and, $or, $not) can be used at the top level.\n- All other operators must be used within a field condition.\n Valid: { \"field\": { \"$gt\": 100 } }\n Valid: { \"$and\": [...] }\n Invalid: { \"$gt\": 100 }\n- Logical operators must contain field conditions, not direct operators.\n Valid: { \"$and\": [{ \"field\": { \"$gt\": 100 } }] }\n Invalid: { \"$and\": [{ \"$gt\": 100 }] }\n- $not operator:\n - Must be an object\n - Cannot be empty\n - Can be used at field level or top level\n - Valid: { \"$not\": { \"field\": \"value\" } }\n - Valid: { \"field\": { \"$not\": { \"$eq\": \"value\" } } }\n- Array operators work on array fields only.\n- Empty arrays in conditions are handled gracefully.\n- Regex queries are case-sensitive by default; use patterns accordingly.\n\nExample Complex Query:\n{\n \"$and\": [\n { \"category\": { \"$in\": [\"electronics\", \"computers\"] } },\n { \"price\": { \"$gte\": 100, \"$lte\": 1000 } },\n { \"tags\": { \"$all\": [\"premium\"] } },\n { \"rating\": { \"$exists\": true, \"$gt\": 4 } },\n { \"$or\": [\n { \"stock\": { \"$gt\": 0 } },\n { \"preorder\": true }\n ]},\n { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n ]\n}`;\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -704,6 +704,90 @@ var OpenSearchVector = class extends MastraVector {
|
|
|
704
704
|
}
|
|
705
705
|
};
|
|
706
706
|
//#endregion
|
|
707
|
-
|
|
707
|
+
//#region src/vector/prompt.ts
|
|
708
|
+
/**
|
|
709
|
+
* Vector store prompt for OpenSearch. This prompt details supported filter operators, syntax, and usage examples.
|
|
710
|
+
* Use this as a guide for constructing valid filters for OpenSearch vector queries in Mastra.
|
|
711
|
+
*/
|
|
712
|
+
const OPENSEARCH_PROMPT = `When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.
|
|
713
|
+
Important: Do not explain how to construct the filter—use the specified operators and fields to search the content and return relevant results.
|
|
714
|
+
If a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.
|
|
715
|
+
|
|
716
|
+
Basic Comparison Operators:
|
|
717
|
+
- $eq: Exact match (default for field: value)
|
|
718
|
+
Example: { "category": "electronics" }
|
|
719
|
+
- $ne: Not equal
|
|
720
|
+
Example: { "category": { "$ne": "electronics" } }
|
|
721
|
+
- $gt: Greater than
|
|
722
|
+
Example: { "price": { "$gt": 100 } }
|
|
723
|
+
- $gte: Greater than or equal
|
|
724
|
+
Example: { "price": { "$gte": 100 } }
|
|
725
|
+
- $lt: Less than
|
|
726
|
+
Example: { "price": { "$lt": 100 } }
|
|
727
|
+
- $lte: Less than or equal
|
|
728
|
+
Example: { "price": { "$lte": 100 } }
|
|
729
|
+
|
|
730
|
+
Array Operators:
|
|
731
|
+
- $in: Match any value in array
|
|
732
|
+
Example: { "category": { "$in": ["electronics", "books"] } }
|
|
733
|
+
- $nin: Does not match any value in array
|
|
734
|
+
Example: { "category": { "$nin": ["electronics", "books"] } }
|
|
735
|
+
- $all: Match all values in array
|
|
736
|
+
Example: { "tags": { "$all": ["premium", "sale"] } }
|
|
737
|
+
|
|
738
|
+
Logical Operators:
|
|
739
|
+
- $and: Logical AND (implicit when using multiple conditions)
|
|
740
|
+
Example: { "$and": [{ "price": { "$gt": 100 } }, { "category": "electronics" }] }
|
|
741
|
+
- $or: Logical OR
|
|
742
|
+
Example: { "$or": [{ "price": { "$lt": 50 } }, { "category": "books" }] }
|
|
743
|
+
- $not: Logical NOT
|
|
744
|
+
Example: { "$not": { "category": "electronics" } }
|
|
745
|
+
|
|
746
|
+
Element Operators:
|
|
747
|
+
- $exists: Check if field exists
|
|
748
|
+
Example: { "rating": { "$exists": true } }
|
|
749
|
+
|
|
750
|
+
Regex Operator:
|
|
751
|
+
- $regex: Match using a regular expression (ECMAScript syntax)
|
|
752
|
+
Example: { "name": { "$regex": "^Sam.*son$" } }
|
|
753
|
+
Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.
|
|
754
|
+
|
|
755
|
+
Restrictions:
|
|
756
|
+
- Nested fields are supported using dot notation (e.g., "address.city").
|
|
757
|
+
- Multiple conditions on the same field are supported (e.g., { "price": { "$gte": 100, "$lte": 1000 } }).
|
|
758
|
+
- Only logical operators ($and, $or, $not) can be used at the top level.
|
|
759
|
+
- All other operators must be used within a field condition.
|
|
760
|
+
Valid: { "field": { "$gt": 100 } }
|
|
761
|
+
Valid: { "$and": [...] }
|
|
762
|
+
Invalid: { "$gt": 100 }
|
|
763
|
+
- Logical operators must contain field conditions, not direct operators.
|
|
764
|
+
Valid: { "$and": [{ "field": { "$gt": 100 } }] }
|
|
765
|
+
Invalid: { "$and": [{ "$gt": 100 }] }
|
|
766
|
+
- $not operator:
|
|
767
|
+
- Must be an object
|
|
768
|
+
- Cannot be empty
|
|
769
|
+
- Can be used at field level or top level
|
|
770
|
+
- Valid: { "$not": { "field": "value" } }
|
|
771
|
+
- Valid: { "field": { "$not": { "$eq": "value" } } }
|
|
772
|
+
- Array operators work on array fields only.
|
|
773
|
+
- Empty arrays in conditions are handled gracefully.
|
|
774
|
+
- Regex queries are case-sensitive by default; use patterns accordingly.
|
|
775
|
+
|
|
776
|
+
Example Complex Query:
|
|
777
|
+
{
|
|
778
|
+
"$and": [
|
|
779
|
+
{ "category": { "$in": ["electronics", "computers"] } },
|
|
780
|
+
{ "price": { "$gte": 100, "$lte": 1000 } },
|
|
781
|
+
{ "tags": { "$all": ["premium"] } },
|
|
782
|
+
{ "rating": { "$exists": true, "$gt": 4 } },
|
|
783
|
+
{ "$or": [
|
|
784
|
+
{ "stock": { "$gt": 0 } },
|
|
785
|
+
{ "preorder": true }
|
|
786
|
+
]},
|
|
787
|
+
{ "name": { "$regex": "^Sam.*son$" } }
|
|
788
|
+
]
|
|
789
|
+
}`;
|
|
790
|
+
//#endregion
|
|
791
|
+
export { OPENSEARCH_PROMPT, OpenSearchVector };
|
|
708
792
|
|
|
709
793
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["OpenSearchClient"],"sources":["../src/vector/filter.ts","../src/vector/index.ts"],"sourcesContent":["import type {\n BlacklistedRootOperators,\n LogicalOperatorValueMap,\n OperatorSupport,\n OperatorValueMap,\n QueryOperator,\n VectorFilter,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\n\ntype OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;\n\ntype OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';\n\nexport type OpenSearchVectorFilter = VectorFilter<\n keyof OpenSearchOperatorValueMap,\n OpenSearchOperatorValueMap,\n OpenSearchLogicalOperatorValueMap,\n OpenSearchBlacklisted\n>;\n/**\n * Translator for OpenSearch filter queries.\n * Maintains OpenSearch-compatible syntax while ensuring proper validation\n * and normalization of values.\n */\nexport class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or', '$not'],\n array: ['$in', '$nin', '$all'],\n regex: ['$regex'],\n custom: [],\n };\n }\n\n translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter {\n if (this.isEmpty(filter)) return undefined;\n this.validateFilter(filter);\n return this.translateNode(filter);\n }\n\n private translateNode(node: OpenSearchVectorFilter): any {\n // Handle primitive values and arrays\n if (this.isPrimitive(node) || Array.isArray(node)) {\n return node;\n }\n\n const entries = Object.entries(node as Record<string, any>);\n\n // Extract logical operators and field conditions\n const logicalOperators: [string, any][] = [];\n const fieldConditions: [string, any][] = [];\n\n entries.forEach(([key, value]) => {\n if (this.isLogicalOperator(key)) {\n logicalOperators.push([key, value]);\n } else {\n fieldConditions.push([key, value]);\n }\n });\n\n // If we have a single logical operator\n if (logicalOperators.length === 1 && fieldConditions.length === 0) {\n const [operator, value] = logicalOperators[0] as [QueryOperator, any];\n if (!Array.isArray(value) && typeof value !== 'object') {\n throw new Error(`Invalid logical operator structure: ${operator} must have an array or object value`);\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // Process field conditions\n const fieldConditionQueries = fieldConditions.map(([key, value]) => {\n // Handle nested objects\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Check if the object contains operators\n const hasOperators = Object.keys(value).some(k => this.isOperator(k));\n\n // Use a more direct approach based on whether operators are present\n const nestedField = `metadata.${key}`;\n return hasOperators\n ? this.translateFieldConditions(nestedField, value)\n : this.translateNestedObject(nestedField, value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { terms: { [fieldWithKeyword]: value } };\n }\n\n // Handle simple field equality\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { term: { [fieldWithKeyword]: value } };\n });\n\n // Handle case with both logical operators and field conditions or multiple logical operators\n if (logicalOperators.length > 0) {\n const logicalConditions = logicalOperators.map(([operator, value]) =>\n this.translateOperator(operator as QueryOperator, value),\n );\n\n return {\n bool: {\n must: [...logicalConditions, ...fieldConditionQueries],\n },\n };\n }\n\n // If we only have field conditions\n if (fieldConditionQueries.length > 1) {\n return {\n bool: {\n must: fieldConditionQueries,\n },\n };\n }\n\n // If we have only one field condition\n if (fieldConditionQueries.length === 1) {\n return fieldConditionQueries[0];\n }\n\n // If we have no conditions (e.g., only empty $and arrays)\n return { match_all: {} };\n }\n\n /**\n * Handles translation of nested objects with dot notation fields\n */\n private translateNestedObject(field: string, value: Record<string, any>): any {\n const conditions = Object.entries(value).map(([subField, subValue]) => {\n const fullField = `${field}.${subField}`;\n\n // Check if this is an operator in a nested field\n if (this.isOperator(subField)) {\n return this.translateOperator(subField as QueryOperator, subValue, field);\n }\n\n if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {\n // Check if the nested object contains operators\n const hasOperators = Object.keys(subValue).some(k => this.isOperator(k));\n if (hasOperators) {\n return this.translateFieldConditions(fullField, subValue);\n }\n return this.translateNestedObject(fullField, subValue);\n }\n const fieldWithKeyword = this.addKeywordIfNeeded(fullField, subValue);\n return { term: { [fieldWithKeyword]: subValue } };\n });\n\n return {\n bool: {\n must: conditions,\n },\n };\n }\n\n private translateLogicalOperator(operator: QueryOperator, value: any): any {\n const conditions = Array.isArray(value) ? value.map(item => this.translateNode(item)) : [this.translateNode(value)];\n switch (operator) {\n case '$and':\n // For empty $and, return a query that matches everything\n if (Array.isArray(value) && value.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must: conditions,\n },\n };\n case '$or':\n // For empty $or, return a query that matches nothing\n if (Array.isArray(value) && value.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n should: conditions,\n },\n };\n case '$not':\n return {\n bool: {\n must_not: conditions,\n },\n };\n default:\n return value;\n }\n }\n\n private translateFieldOperator(field: string, operator: QueryOperator, value: any): any {\n // Handle basic comparison operators\n if (this.isBasicOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$eq':\n // Handle null equality: field does not exist or is null\n if (value === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n return { term: { [fieldWithKeyword]: normalizedValue } };\n case '$ne':\n // Handle null inequality: field exists (i.e., is not null)\n if (value === null) {\n return { exists: { field } };\n }\n return {\n bool: {\n must_not: [{ term: { [fieldWithKeyword]: normalizedValue } }],\n },\n };\n default:\n return { term: { [fieldWithKeyword]: normalizedValue } };\n }\n }\n\n // Handle numeric operators\n if (this.isNumericOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const rangeOp = operator.replace('$', '');\n return { range: { [field]: { [rangeOp]: normalizedValue } } };\n }\n\n // Handle array operators\n if (this.isArrayOperator(operator)) {\n if (!Array.isArray(value)) {\n throw new Error(`Invalid array operator value: ${operator} requires an array value`);\n }\n const normalizedValues = this.normalizeArrayValues(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$in':\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n case '$nin':\n // For empty arrays, return a query that matches everything\n if (normalizedValues.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must_not: [{ terms: { [fieldWithKeyword]: normalizedValues } }],\n },\n };\n case '$all':\n // For empty arrays, return a query that will match nothing\n if (normalizedValues.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n must: normalizedValues.map(v => ({ term: { [fieldWithKeyword]: v } })),\n },\n };\n default:\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n }\n }\n\n // Handle element operators\n if (this.isElementOperator(operator)) {\n switch (operator) {\n case '$exists':\n return value ? { exists: { field } } : { bool: { must_not: [{ exists: { field } }] } };\n default:\n return { exists: { field } };\n }\n }\n\n // Handle regex operators\n if (this.isRegexOperator(operator)) {\n return this.translateRegexOperator(field, value);\n }\n\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n return { term: { [fieldWithKeyword]: value } };\n }\n\n /**\n * Translates regex patterns to OpenSearch query syntax\n */\n private translateRegexOperator(field: string, value: any): any {\n // Convert value to string if it's not already\n const regexValue = typeof value === 'string' ? value : value.toString();\n\n // Check for problematic patterns (like newlines, etc.)\n if (regexValue.includes('\\n') || regexValue.includes('\\r')) {\n // For patterns with newlines, use a simpler approach\n // OpenSearch doesn't support dotall flag like JavaScript\n return { match: { [field]: value } };\n }\n\n // Process regex pattern to handle anchors properly\n let processedRegex = regexValue;\n const hasStartAnchor = regexValue.startsWith('^');\n const hasEndAnchor = regexValue.endsWith('$');\n\n // If we have anchors, use wildcard query for better handling\n if (hasStartAnchor || hasEndAnchor) {\n // Remove anchors\n if (hasStartAnchor) {\n processedRegex = processedRegex.substring(1);\n }\n if (hasEndAnchor) {\n processedRegex = processedRegex.substring(0, processedRegex.length - 1);\n }\n\n // Create wildcard pattern\n let wildcardPattern = processedRegex;\n if (!hasStartAnchor) {\n wildcardPattern = '*' + wildcardPattern;\n }\n if (!hasEndAnchor) {\n wildcardPattern = wildcardPattern + '*';\n }\n\n return { wildcard: { [field]: wildcardPattern } };\n }\n\n // Use regexp for other regex patterns\n // Escape any backslashes to prevent OpenSearch from misinterpreting them\n const escapedRegex = regexValue.replace(/\\\\/g, '\\\\\\\\');\n return { regexp: { [field]: escapedRegex } };\n }\n\n private addKeywordIfNeeded(field: string, value: any): string {\n // Add .keyword suffix for string fields\n if (typeof value === 'string') {\n return `${field}.keyword`;\n }\n // Add .keyword suffix for string array fields\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n return `${field}.keyword`;\n }\n return field;\n }\n\n /**\n * Helper method to handle special cases for the $not operator\n */\n private handleNotOperatorSpecialCases(value: any, field: string): any | null {\n // For \"not null\", we need to use exists query\n if (value === null) {\n return { exists: { field } };\n }\n\n if (typeof value === 'object' && value !== null) {\n // For \"not {$eq: null}\", we need to use exists query\n if ('$eq' in value && value.$eq === null) {\n return { exists: { field } };\n }\n\n // For \"not {$ne: null}\", we need to use must_not exists query\n if ('$ne' in value && value.$ne === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n }\n\n return null; // No special case applies\n }\n\n private translateOperator(operator: QueryOperator, value: any, field?: string): any {\n // Check if this is a valid operator\n if (!this.isOperator(operator)) {\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n // Special case for $not with null or $eq: null\n if (operator === '$not' && field) {\n const specialCaseResult = this.handleNotOperatorSpecialCases(value, field);\n if (specialCaseResult) {\n return specialCaseResult;\n }\n }\n\n // Handle logical operators\n if (this.isLogicalOperator(operator)) {\n // For $not operator with field context and nested operators, handle specially\n if (operator === '$not' && field && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const entries = Object.entries(value);\n\n // Handle multiple operators in $not\n if (entries.length > 0) {\n // If all entries are operators, handle them as a single condition\n if (entries.every(([op]) => this.isOperator(op))) {\n const translatedCondition = this.translateFieldConditions(field, value);\n return {\n bool: {\n must_not: [translatedCondition],\n },\n };\n }\n\n // Handle single nested operator\n if (entries.length === 1 && entries[0] && this.isOperator(entries[0][0])) {\n const [nestedOp, nestedVal] = entries[0] as [QueryOperator, any];\n const translatedNested = this.translateFieldOperator(field, nestedOp, nestedVal);\n return {\n bool: {\n must_not: [translatedNested],\n },\n };\n }\n }\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // If a field is provided, use translateFieldOperator for more specific translation\n if (field) {\n return this.translateFieldOperator(field, operator, value);\n }\n\n // For non-logical operators without a field context, just return the value\n // The actual translation happens in translateFieldConditions where we have the field context\n return value;\n }\n\n /**\n * Translates field conditions to OpenSearch query syntax\n * Handles special cases like range queries and multiple operators\n */\n private translateFieldConditions(field: string, conditions: Record<string, any>): any {\n // Special case: Optimize multiple numeric operators into a single range query\n if (this.canOptimizeToRangeQuery(conditions)) {\n return this.createRangeQuery(field, conditions);\n }\n\n // Handle all other operators consistently\n const queryConditions: any[] = [];\n Object.entries(conditions).forEach(([operator, value]) => {\n if (this.isOperator(operator)) {\n queryConditions.push(this.translateOperator(operator as QueryOperator, value, field));\n } else {\n // Handle non-operator keys (should not happen in normal usage)\n const fieldWithKeyword = this.addKeywordIfNeeded(`${field}.${operator}`, value);\n queryConditions.push({ term: { [fieldWithKeyword]: value } });\n }\n });\n\n // Return single condition without wrapping\n if (queryConditions.length === 1) {\n return queryConditions[0];\n }\n\n // Combine multiple conditions with AND logic\n return {\n bool: {\n must: queryConditions,\n },\n };\n }\n\n /**\n * Checks if conditions can be optimized to a range query\n */\n private canOptimizeToRangeQuery(conditions: Record<string, any>): boolean {\n return Object.keys(conditions).every(op => this.isNumericOperator(op)) && Object.keys(conditions).length > 0;\n }\n\n /**\n * Creates a range query from numeric operators\n */\n private createRangeQuery(field: string, conditions: Record<string, any>): any {\n const rangeParams = Object.fromEntries(\n Object.entries(conditions).map(([op, val]) => [op.replace('$', ''), this.normalizeComparisonValue(val)]),\n );\n\n return { range: { [field]: rangeParams } };\n }\n}\n","import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { MastraVector, validateUpsert, validateTopK } from '@mastra/core/vector';\nimport { Client as OpenSearchClient } from '@opensearch-project/opensearch';\nimport type { ClientOptions } from '@opensearch-project/opensearch';\nimport { OpenSearchFilterTranslator } from './filter';\nimport type { OpenSearchVectorFilter } from './filter';\n\n/**\n * Configuration for OpenSearchVector.\n *\n * Extends the OpenSearch ClientOptions with a required id.\n * All OpenSearch client options are supported (node, auth, ssl, compression, etc.).\n *\n * @example\n * ```typescript\n * // Simple URL config\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'http://localhost:9200',\n * });\n *\n * // With authentication\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'https://my-opensearch-cluster.com',\n * auth: { username: 'admin', password: 'secret' },\n * ssl: { rejectUnauthorized: false },\n * });\n * ```\n */\nexport type OpenSearchVectorConfig = ClientOptions & { id: string };\n\nconst METRIC_MAPPING = {\n cosine: 'cosinesimil',\n euclidean: 'l2',\n dotproduct: 'innerproduct',\n} as const;\n\nconst REVERSE_METRIC_MAPPING = {\n cosinesimil: 'cosine',\n l2: 'euclidean',\n innerproduct: 'dotproduct',\n} as const;\n\ntype OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;\n\nexport class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {\n private client: OpenSearchClient;\n\n /**\n * Creates a new OpenSearchVector client.\n *\n * @param config - OpenSearch client configuration options plus a required id.\n * @see OpenSearchVectorConfig for all available options.\n */\n constructor({ id, ...clientOptions }: OpenSearchVectorConfig) {\n super({ id });\n this.client = new OpenSearchClient(clientOptions);\n }\n\n /**\n * Creates a new collection with the specified configuration.\n *\n * @param {string} indexName - The name of the collection to create.\n * @param {number} dimension - The dimension of the vectors to be stored in the collection.\n * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.\n * @returns {Promise<void>} A promise that resolves when the collection is created.\n */\n async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {\n if (!Number.isInteger(dimension) || dimension <= 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Dimension must be a positive integer',\n details: { indexName, dimension },\n });\n }\n\n try {\n await this.client.indices.create({\n index: indexName,\n body: {\n settings: { index: { knn: true } },\n mappings: {\n properties: {\n metadata: { type: 'object' },\n id: { type: 'keyword' },\n embedding: {\n type: 'knn_vector',\n dimension: dimension,\n method: {\n name: 'hnsw',\n space_type: METRIC_MAPPING[metric],\n engine: 'faiss',\n parameters: { ef_construction: 128, m: 16 },\n },\n },\n },\n },\n },\n });\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n // Fetch collection info and check dimension\n await this.validateExistingIndex(indexName, dimension, metric);\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n }\n\n /**\n * Lists all indexes.\n *\n * @returns {Promise<string[]>} A promise that resolves to an array of indexes.\n */\n async listIndexes(): Promise<string[]> {\n try {\n const response = await this.client.cat.indices({ format: 'json' });\n const indexes = response.body\n .map((record: { index?: string }) => record.index)\n .filter((index: string | undefined) => index !== undefined);\n\n return indexes;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'LIST_INDEXES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n const { body: indexInfo } = await this.client.indices.get({ index: indexName });\n const mappings = indexInfo[indexName]?.mappings;\n const embedding: any = mappings?.properties?.embedding;\n const spaceType = embedding.method.space_type as keyof typeof REVERSE_METRIC_MAPPING;\n\n const { body: countInfo } = await this.client.count({ index: indexName });\n\n return {\n dimension: Number(embedding.dimension),\n count: Number(countInfo.count),\n metric: REVERSE_METRIC_MAPPING[spaceType],\n };\n }\n\n /**\n * Deletes the specified index.\n *\n * @param {string} indexName - The name of the index to delete.\n * @returns {Promise<void>} A promise that resolves when the index is deleted.\n */\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n await this.client.indices.delete({ index: indexName });\n } catch (error) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n }\n }\n\n /**\n * Inserts or updates vectors in the specified collection.\n *\n * @param {string} indexName - The name of the collection to upsert into.\n * @param {number[][]} vectors - An array of vectors to upsert.\n * @param {Record<string, any>[]} [metadata] - An optional array of metadata objects corresponding to each vector.\n * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.\n * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.\n */\n async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {\n // Validate input parameters and vector values\n validateUpsert('OPENSEARCH', vectors, metadata, ids, true);\n\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const operations = [];\n\n try {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions(vectors, indexInfo.dimension);\n\n for (let i = 0; i < vectors.length; i++) {\n const operation = {\n index: {\n _index: indexName,\n _id: vectorIds[i],\n },\n };\n\n const document = {\n id: vectorIds[i],\n embedding: vectors[i],\n metadata: metadata[i] || {},\n };\n\n operations.push(operation);\n operations.push(document);\n }\n\n if (operations.length > 0) {\n await this.client.bulk({ body: operations, refresh: true });\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, vectorCount: vectors?.length || 0 },\n },\n error,\n );\n }\n }\n\n /**\n * Queries the specified collection using a vector and optional filter.\n *\n * @param {string} indexName - The name of the collection to query.\n * @param {number[]} queryVector - The vector to query with.\n * @param {number} [topK] - The maximum number of results to return.\n * @param {Record<string, any>} [filter] - An optional filter to apply to the query. For more on filters in OpenSearch, see the filtering reference: https://opensearch.org/docs/latest/query-dsl/\n * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.\n * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.\n */\n async query({\n indexName,\n queryVector,\n filter,\n topK = 10,\n includeVector = false,\n }: OpenSearchVectorParams): Promise<QueryResult[]> {\n if (!queryVector) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'MISSING_VECTOR'),\n text: 'queryVector is required for OpenSearch queries. Metadata-only queries are not supported by this vector store.',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n });\n }\n\n // Validate topK parameter\n validateTopK('OPENSEARCH', topK);\n\n try {\n const translatedFilter = this.transformFilter(filter);\n\n const response = await this.client.search({\n index: indexName,\n body: {\n query: {\n bool: {\n must: { knn: { embedding: { vector: queryVector, k: topK } } },\n filter: translatedFilter ? [translatedFilter] : [],\n },\n },\n _source: ['id', 'metadata', 'embedding'],\n },\n });\n\n const results = response.body.hits.hits.map((hit: any) => {\n const source = hit._source || {};\n return {\n id: String(source.id || ''),\n score: typeof hit._score === 'number' ? hit._score : 0,\n metadata: source.metadata || {},\n ...(includeVector && { vector: source.embedding as number[] }),\n };\n });\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, topK },\n },\n error,\n );\n }\n }\n\n /**\n * Validates the dimensions of the vectors.\n *\n * @param {number[][]} vectors - The vectors to validate.\n * @param {number} dimension - The dimension of the vectors.\n * @returns {void}\n */\n private validateVectorDimensions(vectors: number[][], dimension: number) {\n if (vectors.some(vector => vector.length !== dimension)) {\n throw new Error('Vector dimension does not match index dimension');\n }\n }\n\n /**\n * Transforms the filter to the OpenSearch DSL.\n *\n * @param {OpenSearchVectorFilter} filter - The filter to transform.\n * @returns {Record<string, any>} The transformed filter.\n */\n private transformFilter(filter?: OpenSearchVectorFilter): any {\n const translator = new OpenSearchFilterTranslator();\n return translator.translate(filter);\n }\n\n /**\n * Updates vectors by ID or filter with the provided vector and/or metadata.\n * @param params - Parameters containing either id or filter for targeting vectors to update\n * @param params.indexName - The name of the index containing the vector(s).\n * @param params.id - The ID of a single vector to update (mutually exclusive with filter).\n * @param params.filter - A filter to match multiple vectors to update (mutually exclusive with id).\n * @param params.update - An object containing the vector and/or metadata to update.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector(params: UpdateVectorParams<OpenSearchVectorFilter>): Promise<void> {\n const { indexName, update } = params;\n\n // Validate mutually exclusive parameters\n if ('id' in params && 'filter' in params && params.id && params.filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'id and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!update.vector && !update.metadata) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_UPDATES'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'No updates provided',\n details: { indexName },\n });\n }\n\n // Validate empty filter\n if ('filter' in params && params.filter && Object.keys(params.filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot update with empty filter',\n details: { indexName },\n });\n }\n\n // Type-narrowing: check if updating by id or by filter\n if ('id' in params && params.id) {\n // Update by ID\n await this.updateVectorById(indexName, params.id, update);\n } else if ('filter' in params && params.filter) {\n // Update by filter\n await this.updateVectorsByFilter(indexName, params.filter, update);\n } else {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either id or filter must be provided',\n details: { indexName },\n });\n }\n }\n\n /**\n * Updates a single vector by its ID.\n */\n private async updateVectorById(\n indexName: string,\n id: string,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n let existingDoc;\n try {\n // First get the current document to merge with updates\n const { body } = await this.client\n .get({\n index: indexName,\n id: id,\n })\n .catch(() => {\n throw new Error(`Document with ID ${id} not found in index ${indexName}`);\n });\n\n if (!body || !body._source) {\n throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);\n }\n existingDoc = body;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n\n const source = existingDoc._source;\n const updatedDoc: Record<string, any> = {\n id: source?.id || id,\n };\n\n try {\n // Update vector if provided\n if (update.vector) {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions([update.vector], indexInfo.dimension);\n\n updatedDoc.embedding = update.vector;\n } else if (source?.embedding) {\n updatedDoc.embedding = source.embedding;\n }\n\n // Update metadata if provided\n if (update.metadata) {\n updatedDoc.metadata = update.metadata;\n } else {\n updatedDoc.metadata = source?.metadata || {};\n }\n\n // Update the document\n await this.client.index({\n index: indexName,\n id: id,\n body: updatedDoc,\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Updates multiple vectors matching a filter.\n */\n private async updateVectorsByFilter(\n indexName: string,\n filter: OpenSearchVectorFilter,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n try {\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n // Build the update script\n const scriptSource: string[] = [];\n const scriptParams: Record<string, any> = {};\n\n if (update.vector) {\n scriptSource.push('ctx._source.embedding = params.embedding');\n scriptParams.embedding = update.vector;\n }\n\n if (update.metadata) {\n scriptSource.push('ctx._source.metadata = params.metadata');\n scriptParams.metadata = update.metadata;\n }\n\n // Use update_by_query to update all matching documents\n await this.client.updateByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n script: {\n source: scriptSource.join('; '),\n params: scriptParams,\n lang: 'painless',\n },\n },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR_BY_FILTER', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n filter: JSON.stringify(filter),\n },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n await this.client.delete({\n index: indexName,\n id: id,\n refresh: true,\n });\n } catch (error: unknown) {\n // Don't throw error if document doesn't exist (404)\n if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<OpenSearchVectorFilter>): Promise<void> {\n // Validate mutually exclusive parameters\n if (ids && filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'ids and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!ids && !filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either filter or ids must be provided',\n details: { indexName },\n });\n }\n\n // Validate non-empty arrays and objects\n if (ids && ids.length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_IDS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty ids array',\n details: { indexName },\n });\n }\n\n if (filter && Object.keys(filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty filter',\n details: { indexName },\n });\n }\n\n try {\n if (ids) {\n // Delete by IDs using bulk API\n const bulkBody = ids.flatMap(id => [{ delete: { _index: indexName, _id: id } }]);\n\n await this.client.bulk({\n body: bulkBody,\n refresh: true,\n });\n } else if (filter) {\n // Delete by filter using delete_by_query\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n await this.client.deleteByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n },\n refresh: true,\n });\n }\n } catch (error) {\n if (error instanceof MastraError) throw error;\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(filter && { filter: JSON.stringify(filter) }),\n ...(ids && { idsCount: ids.length }),\n },\n },\n error,\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["OpenSearchClient"],"sources":["../src/vector/filter.ts","../src/vector/index.ts","../src/vector/prompt.ts"],"sourcesContent":["import type {\n BlacklistedRootOperators,\n LogicalOperatorValueMap,\n OperatorSupport,\n OperatorValueMap,\n QueryOperator,\n VectorFilter,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\n\ntype OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;\n\ntype OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';\n\nexport type OpenSearchVectorFilter = VectorFilter<\n keyof OpenSearchOperatorValueMap,\n OpenSearchOperatorValueMap,\n OpenSearchLogicalOperatorValueMap,\n OpenSearchBlacklisted\n>;\n/**\n * Translator for OpenSearch filter queries.\n * Maintains OpenSearch-compatible syntax while ensuring proper validation\n * and normalization of values.\n */\nexport class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or', '$not'],\n array: ['$in', '$nin', '$all'],\n regex: ['$regex'],\n custom: [],\n };\n }\n\n translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter {\n if (this.isEmpty(filter)) return undefined;\n this.validateFilter(filter);\n return this.translateNode(filter);\n }\n\n private translateNode(node: OpenSearchVectorFilter): any {\n // Handle primitive values and arrays\n if (this.isPrimitive(node) || Array.isArray(node)) {\n return node;\n }\n\n const entries = Object.entries(node as Record<string, any>);\n\n // Extract logical operators and field conditions\n const logicalOperators: [string, any][] = [];\n const fieldConditions: [string, any][] = [];\n\n entries.forEach(([key, value]) => {\n if (this.isLogicalOperator(key)) {\n logicalOperators.push([key, value]);\n } else {\n fieldConditions.push([key, value]);\n }\n });\n\n // If we have a single logical operator\n if (logicalOperators.length === 1 && fieldConditions.length === 0) {\n const [operator, value] = logicalOperators[0] as [QueryOperator, any];\n if (!Array.isArray(value) && typeof value !== 'object') {\n throw new Error(`Invalid logical operator structure: ${operator} must have an array or object value`);\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // Process field conditions\n const fieldConditionQueries = fieldConditions.map(([key, value]) => {\n // Handle nested objects\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Check if the object contains operators\n const hasOperators = Object.keys(value).some(k => this.isOperator(k));\n\n // Use a more direct approach based on whether operators are present\n const nestedField = `metadata.${key}`;\n return hasOperators\n ? this.translateFieldConditions(nestedField, value)\n : this.translateNestedObject(nestedField, value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { terms: { [fieldWithKeyword]: value } };\n }\n\n // Handle simple field equality\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { term: { [fieldWithKeyword]: value } };\n });\n\n // Handle case with both logical operators and field conditions or multiple logical operators\n if (logicalOperators.length > 0) {\n const logicalConditions = logicalOperators.map(([operator, value]) =>\n this.translateOperator(operator as QueryOperator, value),\n );\n\n return {\n bool: {\n must: [...logicalConditions, ...fieldConditionQueries],\n },\n };\n }\n\n // If we only have field conditions\n if (fieldConditionQueries.length > 1) {\n return {\n bool: {\n must: fieldConditionQueries,\n },\n };\n }\n\n // If we have only one field condition\n if (fieldConditionQueries.length === 1) {\n return fieldConditionQueries[0];\n }\n\n // If we have no conditions (e.g., only empty $and arrays)\n return { match_all: {} };\n }\n\n /**\n * Handles translation of nested objects with dot notation fields\n */\n private translateNestedObject(field: string, value: Record<string, any>): any {\n const conditions = Object.entries(value).map(([subField, subValue]) => {\n const fullField = `${field}.${subField}`;\n\n // Check if this is an operator in a nested field\n if (this.isOperator(subField)) {\n return this.translateOperator(subField as QueryOperator, subValue, field);\n }\n\n if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {\n // Check if the nested object contains operators\n const hasOperators = Object.keys(subValue).some(k => this.isOperator(k));\n if (hasOperators) {\n return this.translateFieldConditions(fullField, subValue);\n }\n return this.translateNestedObject(fullField, subValue);\n }\n const fieldWithKeyword = this.addKeywordIfNeeded(fullField, subValue);\n return { term: { [fieldWithKeyword]: subValue } };\n });\n\n return {\n bool: {\n must: conditions,\n },\n };\n }\n\n private translateLogicalOperator(operator: QueryOperator, value: any): any {\n const conditions = Array.isArray(value) ? value.map(item => this.translateNode(item)) : [this.translateNode(value)];\n switch (operator) {\n case '$and':\n // For empty $and, return a query that matches everything\n if (Array.isArray(value) && value.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must: conditions,\n },\n };\n case '$or':\n // For empty $or, return a query that matches nothing\n if (Array.isArray(value) && value.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n should: conditions,\n },\n };\n case '$not':\n return {\n bool: {\n must_not: conditions,\n },\n };\n default:\n return value;\n }\n }\n\n private translateFieldOperator(field: string, operator: QueryOperator, value: any): any {\n // Handle basic comparison operators\n if (this.isBasicOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$eq':\n // Handle null equality: field does not exist or is null\n if (value === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n return { term: { [fieldWithKeyword]: normalizedValue } };\n case '$ne':\n // Handle null inequality: field exists (i.e., is not null)\n if (value === null) {\n return { exists: { field } };\n }\n return {\n bool: {\n must_not: [{ term: { [fieldWithKeyword]: normalizedValue } }],\n },\n };\n default:\n return { term: { [fieldWithKeyword]: normalizedValue } };\n }\n }\n\n // Handle numeric operators\n if (this.isNumericOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const rangeOp = operator.replace('$', '');\n return { range: { [field]: { [rangeOp]: normalizedValue } } };\n }\n\n // Handle array operators\n if (this.isArrayOperator(operator)) {\n if (!Array.isArray(value)) {\n throw new Error(`Invalid array operator value: ${operator} requires an array value`);\n }\n const normalizedValues = this.normalizeArrayValues(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$in':\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n case '$nin':\n // For empty arrays, return a query that matches everything\n if (normalizedValues.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must_not: [{ terms: { [fieldWithKeyword]: normalizedValues } }],\n },\n };\n case '$all':\n // For empty arrays, return a query that will match nothing\n if (normalizedValues.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n must: normalizedValues.map(v => ({ term: { [fieldWithKeyword]: v } })),\n },\n };\n default:\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n }\n }\n\n // Handle element operators\n if (this.isElementOperator(operator)) {\n switch (operator) {\n case '$exists':\n return value ? { exists: { field } } : { bool: { must_not: [{ exists: { field } }] } };\n default:\n return { exists: { field } };\n }\n }\n\n // Handle regex operators\n if (this.isRegexOperator(operator)) {\n return this.translateRegexOperator(field, value);\n }\n\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n return { term: { [fieldWithKeyword]: value } };\n }\n\n /**\n * Translates regex patterns to OpenSearch query syntax\n */\n private translateRegexOperator(field: string, value: any): any {\n // Convert value to string if it's not already\n const regexValue = typeof value === 'string' ? value : value.toString();\n\n // Check for problematic patterns (like newlines, etc.)\n if (regexValue.includes('\\n') || regexValue.includes('\\r')) {\n // For patterns with newlines, use a simpler approach\n // OpenSearch doesn't support dotall flag like JavaScript\n return { match: { [field]: value } };\n }\n\n // Process regex pattern to handle anchors properly\n let processedRegex = regexValue;\n const hasStartAnchor = regexValue.startsWith('^');\n const hasEndAnchor = regexValue.endsWith('$');\n\n // If we have anchors, use wildcard query for better handling\n if (hasStartAnchor || hasEndAnchor) {\n // Remove anchors\n if (hasStartAnchor) {\n processedRegex = processedRegex.substring(1);\n }\n if (hasEndAnchor) {\n processedRegex = processedRegex.substring(0, processedRegex.length - 1);\n }\n\n // Create wildcard pattern\n let wildcardPattern = processedRegex;\n if (!hasStartAnchor) {\n wildcardPattern = '*' + wildcardPattern;\n }\n if (!hasEndAnchor) {\n wildcardPattern = wildcardPattern + '*';\n }\n\n return { wildcard: { [field]: wildcardPattern } };\n }\n\n // Use regexp for other regex patterns\n // Escape any backslashes to prevent OpenSearch from misinterpreting them\n const escapedRegex = regexValue.replace(/\\\\/g, '\\\\\\\\');\n return { regexp: { [field]: escapedRegex } };\n }\n\n private addKeywordIfNeeded(field: string, value: any): string {\n // Add .keyword suffix for string fields\n if (typeof value === 'string') {\n return `${field}.keyword`;\n }\n // Add .keyword suffix for string array fields\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n return `${field}.keyword`;\n }\n return field;\n }\n\n /**\n * Helper method to handle special cases for the $not operator\n */\n private handleNotOperatorSpecialCases(value: any, field: string): any | null {\n // For \"not null\", we need to use exists query\n if (value === null) {\n return { exists: { field } };\n }\n\n if (typeof value === 'object' && value !== null) {\n // For \"not {$eq: null}\", we need to use exists query\n if ('$eq' in value && value.$eq === null) {\n return { exists: { field } };\n }\n\n // For \"not {$ne: null}\", we need to use must_not exists query\n if ('$ne' in value && value.$ne === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n }\n\n return null; // No special case applies\n }\n\n private translateOperator(operator: QueryOperator, value: any, field?: string): any {\n // Check if this is a valid operator\n if (!this.isOperator(operator)) {\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n // Special case for $not with null or $eq: null\n if (operator === '$not' && field) {\n const specialCaseResult = this.handleNotOperatorSpecialCases(value, field);\n if (specialCaseResult) {\n return specialCaseResult;\n }\n }\n\n // Handle logical operators\n if (this.isLogicalOperator(operator)) {\n // For $not operator with field context and nested operators, handle specially\n if (operator === '$not' && field && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const entries = Object.entries(value);\n\n // Handle multiple operators in $not\n if (entries.length > 0) {\n // If all entries are operators, handle them as a single condition\n if (entries.every(([op]) => this.isOperator(op))) {\n const translatedCondition = this.translateFieldConditions(field, value);\n return {\n bool: {\n must_not: [translatedCondition],\n },\n };\n }\n\n // Handle single nested operator\n if (entries.length === 1 && entries[0] && this.isOperator(entries[0][0])) {\n const [nestedOp, nestedVal] = entries[0] as [QueryOperator, any];\n const translatedNested = this.translateFieldOperator(field, nestedOp, nestedVal);\n return {\n bool: {\n must_not: [translatedNested],\n },\n };\n }\n }\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // If a field is provided, use translateFieldOperator for more specific translation\n if (field) {\n return this.translateFieldOperator(field, operator, value);\n }\n\n // For non-logical operators without a field context, just return the value\n // The actual translation happens in translateFieldConditions where we have the field context\n return value;\n }\n\n /**\n * Translates field conditions to OpenSearch query syntax\n * Handles special cases like range queries and multiple operators\n */\n private translateFieldConditions(field: string, conditions: Record<string, any>): any {\n // Special case: Optimize multiple numeric operators into a single range query\n if (this.canOptimizeToRangeQuery(conditions)) {\n return this.createRangeQuery(field, conditions);\n }\n\n // Handle all other operators consistently\n const queryConditions: any[] = [];\n Object.entries(conditions).forEach(([operator, value]) => {\n if (this.isOperator(operator)) {\n queryConditions.push(this.translateOperator(operator as QueryOperator, value, field));\n } else {\n // Handle non-operator keys (should not happen in normal usage)\n const fieldWithKeyword = this.addKeywordIfNeeded(`${field}.${operator}`, value);\n queryConditions.push({ term: { [fieldWithKeyword]: value } });\n }\n });\n\n // Return single condition without wrapping\n if (queryConditions.length === 1) {\n return queryConditions[0];\n }\n\n // Combine multiple conditions with AND logic\n return {\n bool: {\n must: queryConditions,\n },\n };\n }\n\n /**\n * Checks if conditions can be optimized to a range query\n */\n private canOptimizeToRangeQuery(conditions: Record<string, any>): boolean {\n return Object.keys(conditions).every(op => this.isNumericOperator(op)) && Object.keys(conditions).length > 0;\n }\n\n /**\n * Creates a range query from numeric operators\n */\n private createRangeQuery(field: string, conditions: Record<string, any>): any {\n const rangeParams = Object.fromEntries(\n Object.entries(conditions).map(([op, val]) => [op.replace('$', ''), this.normalizeComparisonValue(val)]),\n );\n\n return { range: { [field]: rangeParams } };\n }\n}\n","import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { MastraVector, validateUpsert, validateTopK } from '@mastra/core/vector';\nimport { Client as OpenSearchClient } from '@opensearch-project/opensearch';\nimport type { ClientOptions } from '@opensearch-project/opensearch';\nimport { OpenSearchFilterTranslator } from './filter';\nimport type { OpenSearchVectorFilter } from './filter';\n\n/**\n * Configuration for OpenSearchVector.\n *\n * Extends the OpenSearch ClientOptions with a required id.\n * All OpenSearch client options are supported (node, auth, ssl, compression, etc.).\n *\n * @example\n * ```typescript\n * // Simple URL config\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'http://localhost:9200',\n * });\n *\n * // With authentication\n * const vector = new OpenSearchVector({\n * id: 'my-vector',\n * node: 'https://my-opensearch-cluster.com',\n * auth: { username: 'admin', password: 'secret' },\n * ssl: { rejectUnauthorized: false },\n * });\n * ```\n */\nexport type OpenSearchVectorConfig = ClientOptions & { id: string };\n\nconst METRIC_MAPPING = {\n cosine: 'cosinesimil',\n euclidean: 'l2',\n dotproduct: 'innerproduct',\n} as const;\n\nconst REVERSE_METRIC_MAPPING = {\n cosinesimil: 'cosine',\n l2: 'euclidean',\n innerproduct: 'dotproduct',\n} as const;\n\ntype OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;\n\nexport class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {\n private client: OpenSearchClient;\n\n /**\n * Creates a new OpenSearchVector client.\n *\n * @param config - OpenSearch client configuration options plus a required id.\n * @see OpenSearchVectorConfig for all available options.\n */\n constructor({ id, ...clientOptions }: OpenSearchVectorConfig) {\n super({ id });\n this.client = new OpenSearchClient(clientOptions);\n }\n\n /**\n * Creates a new collection with the specified configuration.\n *\n * @param {string} indexName - The name of the collection to create.\n * @param {number} dimension - The dimension of the vectors to be stored in the collection.\n * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.\n * @returns {Promise<void>} A promise that resolves when the collection is created.\n */\n async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {\n if (!Number.isInteger(dimension) || dimension <= 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Dimension must be a positive integer',\n details: { indexName, dimension },\n });\n }\n\n try {\n await this.client.indices.create({\n index: indexName,\n body: {\n settings: { index: { knn: true } },\n mappings: {\n properties: {\n metadata: { type: 'object' },\n id: { type: 'keyword' },\n embedding: {\n type: 'knn_vector',\n dimension: dimension,\n method: {\n name: 'hnsw',\n space_type: METRIC_MAPPING[metric],\n engine: 'faiss',\n parameters: { ef_construction: 128, m: 16 },\n },\n },\n },\n },\n },\n });\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n // Fetch collection info and check dimension\n await this.validateExistingIndex(indexName, dimension, metric);\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'CREATE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n }\n\n /**\n * Lists all indexes.\n *\n * @returns {Promise<string[]>} A promise that resolves to an array of indexes.\n */\n async listIndexes(): Promise<string[]> {\n try {\n const response = await this.client.cat.indices({ format: 'json' });\n const indexes = response.body\n .map((record: { index?: string }) => record.index)\n .filter((index: string | undefined) => index !== undefined);\n\n return indexes;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'LIST_INDEXES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n const { body: indexInfo } = await this.client.indices.get({ index: indexName });\n const mappings = indexInfo[indexName]?.mappings;\n const embedding: any = mappings?.properties?.embedding;\n const spaceType = embedding.method.space_type as keyof typeof REVERSE_METRIC_MAPPING;\n\n const { body: countInfo } = await this.client.count({ index: indexName });\n\n return {\n dimension: Number(embedding.dimension),\n count: Number(countInfo.count),\n metric: REVERSE_METRIC_MAPPING[spaceType],\n };\n }\n\n /**\n * Deletes the specified index.\n *\n * @param {string} indexName - The name of the index to delete.\n * @returns {Promise<void>} A promise that resolves when the index is deleted.\n */\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n await this.client.indices.delete({ index: indexName });\n } catch (error) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n }\n }\n\n /**\n * Inserts or updates vectors in the specified collection.\n *\n * @param {string} indexName - The name of the collection to upsert into.\n * @param {number[][]} vectors - An array of vectors to upsert.\n * @param {Record<string, any>[]} [metadata] - An optional array of metadata objects corresponding to each vector.\n * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.\n * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.\n */\n async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {\n // Validate input parameters and vector values\n validateUpsert('OPENSEARCH', vectors, metadata, ids, true);\n\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const operations = [];\n\n try {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions(vectors, indexInfo.dimension);\n\n for (let i = 0; i < vectors.length; i++) {\n const operation = {\n index: {\n _index: indexName,\n _id: vectorIds[i],\n },\n };\n\n const document = {\n id: vectorIds[i],\n embedding: vectors[i],\n metadata: metadata[i] || {},\n };\n\n operations.push(operation);\n operations.push(document);\n }\n\n if (operations.length > 0) {\n await this.client.bulk({ body: operations, refresh: true });\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, vectorCount: vectors?.length || 0 },\n },\n error,\n );\n }\n }\n\n /**\n * Queries the specified collection using a vector and optional filter.\n *\n * @param {string} indexName - The name of the collection to query.\n * @param {number[]} queryVector - The vector to query with.\n * @param {number} [topK] - The maximum number of results to return.\n * @param {Record<string, any>} [filter] - An optional filter to apply to the query. For more on filters in OpenSearch, see the filtering reference: https://opensearch.org/docs/latest/query-dsl/\n * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.\n * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.\n */\n async query({\n indexName,\n queryVector,\n filter,\n topK = 10,\n includeVector = false,\n }: OpenSearchVectorParams): Promise<QueryResult[]> {\n if (!queryVector) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'MISSING_VECTOR'),\n text: 'queryVector is required for OpenSearch queries. Metadata-only queries are not supported by this vector store.',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n });\n }\n\n // Validate topK parameter\n validateTopK('OPENSEARCH', topK);\n\n try {\n const translatedFilter = this.transformFilter(filter);\n\n const response = await this.client.search({\n index: indexName,\n body: {\n query: {\n bool: {\n must: { knn: { embedding: { vector: queryVector, k: topK } } },\n filter: translatedFilter ? [translatedFilter] : [],\n },\n },\n _source: ['id', 'metadata', 'embedding'],\n },\n });\n\n const results = response.body.hits.hits.map((hit: any) => {\n const source = hit._source || {};\n return {\n id: String(source.id || ''),\n score: typeof hit._score === 'number' ? hit._score : 0,\n metadata: source.metadata || {},\n ...(includeVector && { vector: source.embedding as number[] }),\n };\n });\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'QUERY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, topK },\n },\n error,\n );\n }\n }\n\n /**\n * Validates the dimensions of the vectors.\n *\n * @param {number[][]} vectors - The vectors to validate.\n * @param {number} dimension - The dimension of the vectors.\n * @returns {void}\n */\n private validateVectorDimensions(vectors: number[][], dimension: number) {\n if (vectors.some(vector => vector.length !== dimension)) {\n throw new Error('Vector dimension does not match index dimension');\n }\n }\n\n /**\n * Transforms the filter to the OpenSearch DSL.\n *\n * @param {OpenSearchVectorFilter} filter - The filter to transform.\n * @returns {Record<string, any>} The transformed filter.\n */\n private transformFilter(filter?: OpenSearchVectorFilter): any {\n const translator = new OpenSearchFilterTranslator();\n return translator.translate(filter);\n }\n\n /**\n * Updates vectors by ID or filter with the provided vector and/or metadata.\n * @param params - Parameters containing either id or filter for targeting vectors to update\n * @param params.indexName - The name of the index containing the vector(s).\n * @param params.id - The ID of a single vector to update (mutually exclusive with filter).\n * @param params.filter - A filter to match multiple vectors to update (mutually exclusive with id).\n * @param params.update - An object containing the vector and/or metadata to update.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector(params: UpdateVectorParams<OpenSearchVectorFilter>): Promise<void> {\n const { indexName, update } = params;\n\n // Validate mutually exclusive parameters\n if ('id' in params && 'filter' in params && params.id && params.filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'id and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!update.vector && !update.metadata) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_UPDATES'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'No updates provided',\n details: { indexName },\n });\n }\n\n // Validate empty filter\n if ('filter' in params && params.filter && Object.keys(params.filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot update with empty filter',\n details: { indexName },\n });\n }\n\n // Type-narrowing: check if updating by id or by filter\n if ('id' in params && params.id) {\n // Update by ID\n await this.updateVectorById(indexName, params.id, update);\n } else if ('filter' in params && params.filter) {\n // Update by filter\n await this.updateVectorsByFilter(indexName, params.filter, update);\n } else {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either id or filter must be provided',\n details: { indexName },\n });\n }\n }\n\n /**\n * Updates a single vector by its ID.\n */\n private async updateVectorById(\n indexName: string,\n id: string,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n let existingDoc;\n try {\n // First get the current document to merge with updates\n const { body } = await this.client\n .get({\n index: indexName,\n id: id,\n })\n .catch(() => {\n throw new Error(`Document with ID ${id} not found in index ${indexName}`);\n });\n\n if (!body || !body._source) {\n throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);\n }\n existingDoc = body;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n\n const source = existingDoc._source;\n const updatedDoc: Record<string, any> = {\n id: source?.id || id,\n };\n\n try {\n // Update vector if provided\n if (update.vector) {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions([update.vector], indexInfo.dimension);\n\n updatedDoc.embedding = update.vector;\n } else if (source?.embedding) {\n updatedDoc.embedding = source.embedding;\n }\n\n // Update metadata if provided\n if (update.metadata) {\n updatedDoc.metadata = update.metadata;\n } else {\n updatedDoc.metadata = source?.metadata || {};\n }\n\n // Update the document\n await this.client.index({\n index: indexName,\n id: id,\n body: updatedDoc,\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Updates multiple vectors matching a filter.\n */\n private async updateVectorsByFilter(\n indexName: string,\n filter: OpenSearchVectorFilter,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n try {\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n // Build the update script\n const scriptSource: string[] = [];\n const scriptParams: Record<string, any> = {};\n\n if (update.vector) {\n scriptSource.push('ctx._source.embedding = params.embedding');\n scriptParams.embedding = update.vector;\n }\n\n if (update.metadata) {\n scriptSource.push('ctx._source.metadata = params.metadata');\n scriptParams.metadata = update.metadata;\n }\n\n // Use update_by_query to update all matching documents\n await this.client.updateByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n script: {\n source: scriptSource.join('; '),\n params: scriptParams,\n lang: 'painless',\n },\n },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'UPDATE_VECTOR_BY_FILTER', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n filter: JSON.stringify(filter),\n },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n await this.client.delete({\n index: indexName,\n id: id,\n refresh: true,\n });\n } catch (error: unknown) {\n // Don't throw error if document doesn't exist (404)\n if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<OpenSearchVectorFilter>): Promise<void> {\n // Validate mutually exclusive parameters\n if (ids && filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'ids and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!ids && !filter) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either filter or ids must be provided',\n details: { indexName },\n });\n }\n\n // Validate non-empty arrays and objects\n if (ids && ids.length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_IDS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty ids array',\n details: { indexName },\n });\n }\n\n if (filter && Object.keys(filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty filter',\n details: { indexName },\n });\n }\n\n try {\n if (ids) {\n // Delete by IDs using bulk API\n const bulkBody = ids.flatMap(id => [{ delete: { _index: indexName, _id: id } }]);\n\n await this.client.bulk({\n body: bulkBody,\n refresh: true,\n });\n } else if (filter) {\n // Delete by filter using delete_by_query\n const translator = new OpenSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n await this.client.deleteByQuery({\n index: indexName,\n body: {\n query: (translatedFilter as any) || { match_all: {} },\n },\n refresh: true,\n });\n }\n } catch (error) {\n if (error instanceof MastraError) throw error;\n throw new MastraError(\n {\n id: createVectorErrorId('OPENSEARCH', 'DELETE_VECTORS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(filter && { filter: JSON.stringify(filter) }),\n ...(ids && { idsCount: ids.length }),\n },\n },\n error,\n );\n }\n }\n}\n","/**\n * Vector store prompt for OpenSearch. This prompt details supported filter operators, syntax, and usage examples.\n * Use this as a guide for constructing valid filters for OpenSearch vector queries in Mastra.\n */\nexport const OPENSEARCH_PROMPT = `When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.\nImportant: Do not explain how to construct the filter—use the specified operators and fields to search the content and return relevant results.\nIf a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.\n\nBasic Comparison Operators:\n- $eq: Exact match (default for field: value)\n Example: { \"category\": \"electronics\" }\n- $ne: Not equal\n Example: { \"category\": { \"$ne\": \"electronics\" } }\n- $gt: Greater than\n Example: { \"price\": { \"$gt\": 100 } }\n- $gte: Greater than or equal\n Example: { \"price\": { \"$gte\": 100 } }\n- $lt: Less than\n Example: { \"price\": { \"$lt\": 100 } }\n- $lte: Less than or equal\n Example: { \"price\": { \"$lte\": 100 } }\n\nArray Operators:\n- $in: Match any value in array\n Example: { \"category\": { \"$in\": [\"electronics\", \"books\"] } }\n- $nin: Does not match any value in array\n Example: { \"category\": { \"$nin\": [\"electronics\", \"books\"] } }\n- $all: Match all values in array\n Example: { \"tags\": { \"$all\": [\"premium\", \"sale\"] } }\n\nLogical Operators:\n- $and: Logical AND (implicit when using multiple conditions)\n Example: { \"$and\": [{ \"price\": { \"$gt\": 100 } }, { \"category\": \"electronics\" }] }\n- $or: Logical OR\n Example: { \"$or\": [{ \"price\": { \"$lt\": 50 } }, { \"category\": \"books\" }] }\n- $not: Logical NOT\n Example: { \"$not\": { \"category\": \"electronics\" } }\n\nElement Operators:\n- $exists: Check if field exists\n Example: { \"rating\": { \"$exists\": true } }\n\nRegex Operator:\n- $regex: Match using a regular expression (ECMAScript syntax)\n Example: { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.\n\nRestrictions:\n- Nested fields are supported using dot notation (e.g., \"address.city\").\n- Multiple conditions on the same field are supported (e.g., { \"price\": { \"$gte\": 100, \"$lte\": 1000 } }).\n- Only logical operators ($and, $or, $not) can be used at the top level.\n- All other operators must be used within a field condition.\n Valid: { \"field\": { \"$gt\": 100 } }\n Valid: { \"$and\": [...] }\n Invalid: { \"$gt\": 100 }\n- Logical operators must contain field conditions, not direct operators.\n Valid: { \"$and\": [{ \"field\": { \"$gt\": 100 } }] }\n Invalid: { \"$and\": [{ \"$gt\": 100 }] }\n- $not operator:\n - Must be an object\n - Cannot be empty\n - Can be used at field level or top level\n - Valid: { \"$not\": { \"field\": \"value\" } }\n - Valid: { \"field\": { \"$not\": { \"$eq\": \"value\" } } }\n- Array operators work on array fields only.\n- Empty arrays in conditions are handled gracefully.\n- Regex queries are case-sensitive by default; use patterns accordingly.\n\nExample Complex Query:\n{\n \"$and\": [\n { \"category\": { \"$in\": [\"electronics\", \"computers\"] } },\n { \"price\": { \"$gte\": 100, \"$lte\": 1000 } },\n { \"tags\": { \"$all\": [\"premium\"] } },\n { \"rating\": { \"$exists\": true, \"$gt\": 4 } },\n { \"$or\": [\n { \"stock\": { \"$gt\": 0 } },\n { \"preorder\": true }\n ]},\n { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n ]\n}`;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/opensearch",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2-alpha.0",
|
|
4
4
|
"description": "OpenSearch vector store provider for Mastra",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,17 +23,17 @@
|
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "22.20.1",
|
|
26
|
-
"@vitest/coverage-v8": "4.1.
|
|
27
|
-
"@vitest/ui": "4.1.
|
|
26
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
27
|
+
"@vitest/ui": "4.1.11",
|
|
28
28
|
"eslint": "^10.7.0",
|
|
29
29
|
"tsdown": "0.22.9",
|
|
30
30
|
"tsx": "^4.23.1",
|
|
31
31
|
"typescript": "^7.0.2",
|
|
32
|
-
"vitest": "4.1.
|
|
33
|
-
"@internal/
|
|
34
|
-
"@internal/
|
|
35
|
-
"@internal/
|
|
36
|
-
"@mastra/core": "1.
|
|
32
|
+
"vitest": "4.1.11",
|
|
33
|
+
"@internal/lint": "0.0.141",
|
|
34
|
+
"@internal/types-builder": "0.0.116",
|
|
35
|
+
"@internal/storage-test-utils": "0.0.137",
|
|
36
|
+
"@mastra/core": "1.76.0-alpha.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@mastra/core": ">=1.0.0-0 <2.0.0-0"
|