@mastra/oracledb 0.0.0 → 0.2.0-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.
Files changed (92) hide show
  1. package/LICENSE.md +30 -0
  2. package/dist/docs/SKILL.md +37 -0
  3. package/dist/docs/assets/SOURCE_MAP.json +6 -0
  4. package/dist/docs/references/docs-memory-observational-memory.md +835 -0
  5. package/dist/docs/references/docs-memory-semantic-recall.md +402 -0
  6. package/dist/docs/references/docs-memory-working-memory.md +432 -0
  7. package/dist/docs/references/docs-storage-overview.md +215 -0
  8. package/dist/docs/references/guides-rag-overview.md +74 -0
  9. package/dist/docs/references/guides-rag-retrieval.md +537 -0
  10. package/dist/docs/references/guides-rag-vector-databases.md +710 -0
  11. package/dist/docs/references/reference-rag-metadata-filters.md +227 -0
  12. package/dist/docs/references/reference-storage-oracledb.md +239 -0
  13. package/dist/docs/references/reference-vectors-oracledb.md +347 -0
  14. package/dist/index.cjs +10217 -0
  15. package/dist/index.cjs.map +1 -0
  16. package/dist/index.d.ts +7 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +10196 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/schema.d.ts +27 -0
  21. package/dist/schema.d.ts.map +1 -0
  22. package/dist/shared/connection.d.ts +46 -0
  23. package/dist/shared/connection.d.ts.map +1 -0
  24. package/dist/storage/db/index.d.ts +128 -0
  25. package/dist/storage/db/index.d.ts.map +1 -0
  26. package/dist/storage/domain-utils.d.ts +18 -0
  27. package/dist/storage/domain-utils.d.ts.map +1 -0
  28. package/dist/storage/domains/agents/index.d.ts +54 -0
  29. package/dist/storage/domains/agents/index.d.ts.map +1 -0
  30. package/dist/storage/domains/mcp-clients/index.d.ts +46 -0
  31. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  32. package/dist/storage/domains/memory/index.d.ts +88 -0
  33. package/dist/storage/domains/memory/index.d.ts.map +1 -0
  34. package/dist/storage/domains/memory/messages.d.ts +37 -0
  35. package/dist/storage/domains/memory/messages.d.ts.map +1 -0
  36. package/dist/storage/domains/memory/observational-buffering.d.ts +7 -0
  37. package/dist/storage/domains/memory/observational-buffering.d.ts.map +1 -0
  38. package/dist/storage/domains/memory/observational.d.ts +56 -0
  39. package/dist/storage/domains/memory/observational.d.ts.map +1 -0
  40. package/dist/storage/domains/memory/resources.d.ts +14 -0
  41. package/dist/storage/domains/memory/resources.d.ts.map +1 -0
  42. package/dist/storage/domains/memory/schema.d.ts +43 -0
  43. package/dist/storage/domains/memory/schema.d.ts.map +1 -0
  44. package/dist/storage/domains/memory/threads.d.ts +37 -0
  45. package/dist/storage/domains/memory/threads.d.ts.map +1 -0
  46. package/dist/storage/domains/memory/utils.d.ts +68 -0
  47. package/dist/storage/domains/memory/utils.d.ts.map +1 -0
  48. package/dist/storage/domains/observability/binds.d.ts +21 -0
  49. package/dist/storage/domains/observability/binds.d.ts.map +1 -0
  50. package/dist/storage/domains/observability/index.d.ts +49 -0
  51. package/dist/storage/domains/observability/index.d.ts.map +1 -0
  52. package/dist/storage/domains/observability/logs.d.ts +5 -0
  53. package/dist/storage/domains/observability/logs.d.ts.map +1 -0
  54. package/dist/storage/domains/observability/schema.d.ts +38 -0
  55. package/dist/storage/domains/observability/schema.d.ts.map +1 -0
  56. package/dist/storage/domains/observability/scores-bridge.d.ts +7 -0
  57. package/dist/storage/domains/observability/scores-bridge.d.ts.map +1 -0
  58. package/dist/storage/domains/observability/spans.d.ts +18 -0
  59. package/dist/storage/domains/observability/spans.d.ts.map +1 -0
  60. package/dist/storage/domains/scorer-definitions/index.d.ts +46 -0
  61. package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -0
  62. package/dist/storage/domains/scores/index.d.ts +63 -0
  63. package/dist/storage/domains/scores/index.d.ts.map +1 -0
  64. package/dist/storage/domains/workflows/index.d.ts +61 -0
  65. package/dist/storage/domains/workflows/index.d.ts.map +1 -0
  66. package/dist/storage/index.d.ts +45 -0
  67. package/dist/storage/index.d.ts.map +1 -0
  68. package/dist/storage/migrations.d.ts +55 -0
  69. package/dist/storage/migrations.d.ts.map +1 -0
  70. package/dist/storage/types.d.ts +44 -0
  71. package/dist/storage/types.d.ts.map +1 -0
  72. package/dist/vector/ddl.d.ts +58 -0
  73. package/dist/vector/ddl.d.ts.map +1 -0
  74. package/dist/vector/filter.d.ts +7 -0
  75. package/dist/vector/filter.d.ts.map +1 -0
  76. package/dist/vector/identifiers.d.ts +11 -0
  77. package/dist/vector/identifiers.d.ts.map +1 -0
  78. package/dist/vector/index.d.ts +32 -0
  79. package/dist/vector/index.d.ts.map +1 -0
  80. package/dist/vector/prompt.d.ts +6 -0
  81. package/dist/vector/prompt.d.ts.map +1 -0
  82. package/dist/vector/query.d.ts +5 -0
  83. package/dist/vector/query.d.ts.map +1 -0
  84. package/dist/vector/sql.d.ts +12 -0
  85. package/dist/vector/sql.d.ts.map +1 -0
  86. package/dist/vector/stats.d.ts +9 -0
  87. package/dist/vector/stats.d.ts.map +1 -0
  88. package/dist/vector/types.d.ts +80 -0
  89. package/dist/vector/types.d.ts.map +1 -0
  90. package/dist/vector/upsert.d.ts +20 -0
  91. package/dist/vector/upsert.d.ts.map +1 -0
  92. package/package.json +23 -24
@@ -0,0 +1,710 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
3
+ # Storing embeddings in a vector database
4
+
5
+ After generating embeddings, you need to store them in a database that supports vector similarity search. Mastra provides a consistent interface for storing and querying embeddings across vector databases.
6
+
7
+ ## Supported databases
8
+
9
+ **MongoDB**:
10
+
11
+ ```ts
12
+ import { MongoDBVector } from '@mastra/mongodb'
13
+
14
+ const store = new MongoDBVector({
15
+ id: 'mongodb-vector',
16
+ uri: process.env.MONGODB_URI,
17
+ dbName: process.env.MONGODB_DB_NAME,
18
+ })
19
+ await store.createIndex({
20
+ indexName: 'myCollection',
21
+ dimension: 1536,
22
+ })
23
+ await store.upsert({
24
+ indexName: 'myCollection',
25
+ vectors: embeddings,
26
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
27
+ })
28
+ ```
29
+
30
+ ### Using MongoDB Atlas Vector Search
31
+
32
+ For detailed setup instructions and best practices, see the [official MongoDB Atlas Vector Search documentation](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-overview/?utm_campaign=devrel\&utm_source=third-party-content\&utm_medium=cta\&utm_content=mastra-docs).
33
+
34
+ ### Using VoyageAI with MongoDB
35
+
36
+ MongoDB works seamlessly with VoyageAI's embedding models, which are optimized for retrieval tasks. For complete examples and specialized models, see the [VoyageAI embeddings documentation](https://mastra.ai/models/embeddings) and [MongoDB vector reference](https://mastra.ai/reference/vectors/mongodb).
37
+
38
+ ### Hybrid Search (Vector + Full-Text)
39
+
40
+ MongoDB supports hybrid search that fuses vector similarity with BM25 full-text search using server-side `$rankFusion` (requires MongoDB >= 8.0; generally available from 8.1, and enabled on Atlas 8.0.x). This is useful when you want to combine semantic and keyword-based retrieval:
41
+
42
+ ```ts
43
+ await store.createSearchIndex({ indexName: 'myCollection', fields: ['text'] })
44
+ const results = await store.hybridQuery({
45
+ indexName: 'myCollection',
46
+ queryVector: embedding,
47
+ query: 'search terms',
48
+ paths: ['text'],
49
+ topK: 10,
50
+ })
51
+ ```
52
+
53
+ See the [MongoDB vector reference](https://mastra.ai/reference/vectors/mongodb) for details on `createSearchIndex()`, `textQuery()`, and `hybridQuery()`.
54
+
55
+ **PgVector**:
56
+
57
+ ```ts
58
+ import { PgVector } from '@mastra/pg'
59
+
60
+ const store = new PgVector({
61
+ id: 'pg-vector',
62
+ connectionString: process.env.POSTGRES_CONNECTION_STRING,
63
+ })
64
+
65
+ await store.createIndex({
66
+ indexName: 'myCollection',
67
+ dimension: 1536,
68
+ })
69
+
70
+ await store.upsert({
71
+ indexName: 'myCollection',
72
+ vectors: embeddings,
73
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
74
+ })
75
+ ```
76
+
77
+ ### Using PostgreSQL with pgvector
78
+
79
+ PostgreSQL with the pgvector extension is a good solution for teams already using PostgreSQL who want to minimize infrastructure complexity. For detailed setup instructions and best practices, see the [official pgvector repository](https://github.com/pgvector/pgvector).
80
+
81
+ **OracleDB**:
82
+
83
+ ```ts
84
+ import { OracleVector } from '@mastra/oracledb'
85
+
86
+ const store = new OracleVector({
87
+ id: 'oracle-vector',
88
+ user: process.env.ORACLE_DATABASE_USER,
89
+ password: process.env.ORACLE_DATABASE_PASSWORD,
90
+ connectString: process.env.ORACLE_DATABASE_CONNECT_STRING,
91
+ })
92
+
93
+ await store.createIndex({
94
+ indexName: 'myCollection',
95
+ dimension: 1536,
96
+ indexConfig: { type: 'none' },
97
+ })
98
+
99
+ await store.upsert({
100
+ indexName: 'myCollection',
101
+ vectors: embeddings,
102
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
103
+ })
104
+ ```
105
+
106
+ ### Using Oracle Database Vector Search
107
+
108
+ OracleDB stores embeddings in native `VECTOR` columns and metadata in Oracle JSON. Exact search is the default; HNSW and IVF indexes can be configured for tuned deployments.
109
+
110
+ **Pinecone**:
111
+
112
+ ```ts
113
+ import { PineconeVector } from '@mastra/pinecone'
114
+
115
+ const store = new PineconeVector({
116
+ id: 'pinecone-vector',
117
+ apiKey: process.env.PINECONE_API_KEY,
118
+ })
119
+ await store.createIndex({
120
+ indexName: 'myCollection',
121
+ dimension: 1536,
122
+ })
123
+ await store.upsert({
124
+ indexName: 'myCollection',
125
+ vectors: embeddings,
126
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
127
+ })
128
+ ```
129
+
130
+ **Qdrant**:
131
+
132
+ ```ts
133
+ import { QdrantVector } from '@mastra/qdrant'
134
+
135
+ const store = new QdrantVector({
136
+ id: 'qdrant-vector',
137
+ url: process.env.QDRANT_URL,
138
+ apiKey: process.env.QDRANT_API_KEY,
139
+ })
140
+
141
+ await store.createIndex({
142
+ indexName: 'myCollection',
143
+ dimension: 1536,
144
+ })
145
+
146
+ await store.upsert({
147
+ indexName: 'myCollection',
148
+ vectors: embeddings,
149
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
150
+ })
151
+ ```
152
+
153
+ **Chroma**:
154
+
155
+ ```ts
156
+ import { ChromaVector } from '@mastra/chroma'
157
+
158
+ // Running Chroma locally
159
+ // const store = new ChromaVector()
160
+
161
+ // Running on Chroma Cloud
162
+ const store = new ChromaVector({
163
+ id: 'chroma-vector',
164
+ apiKey: process.env.CHROMA_API_KEY,
165
+ tenant: process.env.CHROMA_TENANT,
166
+ database: process.env.CHROMA_DATABASE,
167
+ })
168
+
169
+ await store.createIndex({
170
+ indexName: 'myCollection',
171
+ dimension: 1536,
172
+ })
173
+
174
+ await store.upsert({
175
+ indexName: 'myCollection',
176
+ vectors: embeddings,
177
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
178
+ })
179
+ ```
180
+
181
+ **Astra**:
182
+
183
+ ```ts
184
+ import { AstraVector } from '@mastra/astra'
185
+
186
+ const store = new AstraVector({
187
+ id: 'astra-vector',
188
+ token: process.env.ASTRA_DB_TOKEN,
189
+ endpoint: process.env.ASTRA_DB_ENDPOINT,
190
+ keyspace: process.env.ASTRA_DB_KEYSPACE,
191
+ })
192
+
193
+ await store.createIndex({
194
+ indexName: 'myCollection',
195
+ dimension: 1536,
196
+ })
197
+
198
+ await store.upsert({
199
+ indexName: 'myCollection',
200
+ vectors: embeddings,
201
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
202
+ })
203
+ ```
204
+
205
+ **libSQL**:
206
+
207
+ ```ts
208
+ import { LibSQLVector } from '@mastra/core/vector/libsql'
209
+
210
+ const store = new LibSQLVector({
211
+ id: 'libsql-vector',
212
+ url: process.env.DATABASE_URL,
213
+ authToken: process.env.DATABASE_AUTH_TOKEN, // Optional: for Turso cloud databases
214
+ })
215
+
216
+ await store.createIndex({
217
+ indexName: 'myCollection',
218
+ dimension: 1536,
219
+ })
220
+
221
+ await store.upsert({
222
+ indexName: 'myCollection',
223
+ vectors: embeddings,
224
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
225
+ })
226
+ ```
227
+
228
+ **Upstash**:
229
+
230
+ ```ts
231
+ import { UpstashVector } from '@mastra/upstash'
232
+
233
+ // In upstash they refer to the store as an index
234
+ const store = new UpstashVector({
235
+ id: 'upstash-vector',
236
+ url: process.env.UPSTASH_URL,
237
+ token: process.env.UPSTASH_TOKEN,
238
+ })
239
+
240
+ // There is no store.createIndex call here, Upstash creates indexes (known as namespaces in Upstash) automatically
241
+ // when you upsert if that namespace does not exist yet.
242
+ await store.upsert({
243
+ indexName: 'myCollection', // the namespace name in Upstash
244
+ vectors: embeddings,
245
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
246
+ })
247
+ ```
248
+
249
+ **Cloudflare**:
250
+
251
+ ```ts
252
+ import { CloudflareVector } from '@mastra/vectorize'
253
+
254
+ const store = new CloudflareVector({
255
+ id: 'cloudflare-vector',
256
+ accountId: process.env.CF_ACCOUNT_ID,
257
+ apiToken: process.env.CF_API_TOKEN,
258
+ })
259
+ await store.createIndex({
260
+ indexName: 'myCollection',
261
+ dimension: 1536,
262
+ })
263
+ await store.upsert({
264
+ indexName: 'myCollection',
265
+ vectors: embeddings,
266
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
267
+ })
268
+ ```
269
+
270
+ **OpenSearch**:
271
+
272
+ ```ts
273
+ import { OpenSearchVector } from '@mastra/opensearch'
274
+
275
+ const store = new OpenSearchVector({ id: 'opensearch', node: process.env.OPENSEARCH_URL })
276
+
277
+ await store.createIndex({
278
+ indexName: 'my-collection',
279
+ dimension: 1536,
280
+ })
281
+
282
+ await store.upsert({
283
+ indexName: 'my-collection',
284
+ vectors: embeddings,
285
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
286
+ })
287
+ ```
288
+
289
+ **Elasticsearch**:
290
+
291
+ ```ts
292
+ import { ElasticSearchVector } from '@mastra/elasticsearch'
293
+
294
+ const store = new ElasticSearchVector({
295
+ id: 'elasticsearch-vector',
296
+ url: process.env.ELASTICSEARCH_URL,
297
+ auth: {
298
+ apiKey: process.env.ELASTICSEARCH_API_KEY,
299
+ },
300
+ })
301
+
302
+ await store.createIndex({
303
+ indexName: 'my-collection',
304
+ dimension: 1536,
305
+ })
306
+
307
+ await store.upsert({
308
+ indexName: 'my-collection',
309
+ vectors: embeddings,
310
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
311
+ })
312
+ ```
313
+
314
+ ### Using Elasticsearch
315
+
316
+ For detailed setup instructions and best practices, see the [official Elasticsearch documentation](https://www.elastic.co/docs/solutions/search/get-started).
317
+
318
+ **Couchbase**:
319
+
320
+ ```ts
321
+ import { CouchbaseVector } from '@mastra/couchbase'
322
+
323
+ const store = new CouchbaseVector({
324
+ id: 'couchbase-vector',
325
+ connectionString: process.env.COUCHBASE_CONNECTION_STRING,
326
+ username: process.env.COUCHBASE_USERNAME,
327
+ password: process.env.COUCHBASE_PASSWORD,
328
+ bucketName: process.env.COUCHBASE_BUCKET,
329
+ scopeName: process.env.COUCHBASE_SCOPE,
330
+ collectionName: process.env.COUCHBASE_COLLECTION,
331
+ })
332
+ await store.createIndex({
333
+ indexName: 'myCollection',
334
+ dimension: 1536,
335
+ })
336
+ await store.upsert({
337
+ indexName: 'myCollection',
338
+ vectors: embeddings,
339
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
340
+ })
341
+ ```
342
+
343
+ **Lance**:
344
+
345
+ ```ts
346
+ import { LanceVectorStore } from '@mastra/lance'
347
+
348
+ const store = await LanceVectorStore.create('/path/to/db')
349
+
350
+ await store.createIndex({
351
+ tableName: 'myVectors',
352
+ indexName: 'myCollection',
353
+ dimension: 1536,
354
+ })
355
+
356
+ await store.upsert({
357
+ tableName: 'myVectors',
358
+ vectors: embeddings,
359
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
360
+ })
361
+ ```
362
+
363
+ ### Using LanceDB
364
+
365
+ LanceDB is an embedded vector database built on the Lance columnar format, suitable for local development or cloud deployment. For detailed setup instructions and best practices, see the [official LanceDB documentation](https://lancedb.github.io/lancedb/).
366
+
367
+ **S3 Vectors**:
368
+
369
+ ```ts
370
+ import { S3Vectors } from '@mastra/s3vectors'
371
+
372
+ const store = new S3Vectors({
373
+ id: 's3-vectors',
374
+ vectorBucketName: 'my-vector-bucket',
375
+ clientConfig: {
376
+ region: 'us-east-1',
377
+ },
378
+ nonFilterableMetadataKeys: ['content'],
379
+ })
380
+
381
+ await store.createIndex({
382
+ indexName: 'my-index',
383
+ dimension: 1536,
384
+ })
385
+ await store.upsert({
386
+ indexName: 'my-index',
387
+ vectors: embeddings,
388
+ metadata: chunks.map(chunk => ({ text: chunk.text })),
389
+ })
390
+ ```
391
+
392
+ ## Using vector storage
393
+
394
+ Once initialized, all vector stores share the same interface for creating indexes, upserting embeddings, and querying.
395
+
396
+ ### Creating Indexes
397
+
398
+ Before storing embeddings, you need to create an index with the appropriate dimension size for your embedding model:
399
+
400
+ ```ts
401
+ // Create an index with dimension 1536 (for text-embedding-3-small)
402
+ await store.createIndex({
403
+ indexName: 'myCollection',
404
+ dimension: 1536,
405
+ })
406
+ ```
407
+
408
+ The dimension size must match the output dimension of your chosen embedding model. Common dimension sizes are:
409
+
410
+ - `OpenAI text-embedding-3-small`: 1536 dimensions (or custom, e.g., 256)
411
+ - `Cohere embed-multilingual-v3`: 1024 dimensions
412
+ - `VoyageAI voyage-3.5`: 1024 dimensions (or custom: 256, 512, 1024, 2048)
413
+ - `Google gemini-embedding-001`: 768 dimensions (or custom)
414
+
415
+ > **Warning:** Index dimensions can't be changed after creation. To use a different model, delete and recreate the index with the new dimension size.
416
+
417
+ ### Naming Rules for Databases
418
+
419
+ Each vector database enforces specific naming conventions for indexes and collections to ensure compatibility and prevent conflicts.
420
+
421
+ **MongoDB**:
422
+
423
+ Collection (index) names must:
424
+
425
+ - Start with a letter or underscore
426
+ - Be up to 120 bytes long
427
+ - Contain only letters, numbers, underscores, or dots
428
+ - Cannot contain `$` or the null character
429
+ - Example: `my_collection.123` is valid
430
+ - Example: `my-index` is not valid (contains hyphen)
431
+ - Example: `My$Collection` is not valid (contains `$`)
432
+
433
+ **PgVector**:
434
+
435
+ Index names must:
436
+
437
+ - Start with a letter or underscore
438
+ - Contain only letters, numbers, and underscores
439
+ - Example: `my_index_123` is valid
440
+ - Example: `my-index` is not valid (contains hyphen)
441
+
442
+ **OracleDB**:
443
+
444
+ Index names are logical Mastra names. OracleDB maps each logical index to a physical Oracle table internally.
445
+
446
+ Logical index names must:
447
+
448
+ - Be non-empty
449
+ - Be 512 characters or fewer
450
+ - Be stable for the lifetime of the vector index
451
+ - Example: `my_collection_123` is valid
452
+ - Example: `customer-support/docs:v1` is valid and is mapped to a safe Oracle table name
453
+
454
+ **Pinecone**:
455
+
456
+ Index names must:
457
+
458
+ - Use only lowercase letters, numbers, and dashes
459
+
460
+ - Not contain dots (used for DNS routing)
461
+
462
+ - Not use non-Latin characters or emojis
463
+
464
+ - Have a combined length (with project ID) under 52 characters
465
+
466
+ - Example: `my-index-123` is valid
467
+ - Example: `my.index` is not valid (contains dot)
468
+
469
+ **Qdrant**:
470
+
471
+ Collection names must:
472
+
473
+ - Be 1-255 characters long
474
+
475
+ - Not contain any of these special characters:
476
+
477
+ - `< > : " / \ | ? *`
478
+ - Null character (`\0`)
479
+ - Unit separator (`\u{1F}`)
480
+
481
+ - Example: `my_collection_123` is valid
482
+
483
+ - Example: `my/collection` is not valid (contains slash)
484
+
485
+ **Chroma**:
486
+
487
+ Collection names must:
488
+
489
+ - Be 3-63 characters long
490
+ - Start and end with a letter or number
491
+ - Contain only letters, numbers, underscores, or hyphens
492
+ - Not contain consecutive periods (..)
493
+ - Not be a valid IPv4 address
494
+ - Example: `my-collection-123` is valid
495
+ - Example: `my..collection` is not valid (consecutive periods)
496
+
497
+ **Astra**:
498
+
499
+ Collection names must:
500
+
501
+ - Not be empty
502
+ - Be 48 characters or less
503
+ - Contain only letters, numbers, and underscores
504
+ - Example: `my_collection_123` is valid
505
+ - Example: `my-collection` is not valid (contains hyphen)
506
+
507
+ **libSQL**:
508
+
509
+ Index names must:
510
+
511
+ - Start with a letter or underscore
512
+ - Contain only letters, numbers, and underscores
513
+ - Example: `my_index_123` is valid
514
+ - Example: `my-index` is not valid (contains hyphen)
515
+
516
+ **Upstash**:
517
+
518
+ Namespace names must:
519
+
520
+ - Be 2-100 characters long
521
+
522
+ - Contain only:
523
+
524
+ - Alphanumeric characters (a-z, A-Z, 0-9)
525
+ - Underscores, hyphens, dots
526
+
527
+ - Not start or end with special characters (\_, -, .)
528
+
529
+ - Can be case-sensitive
530
+
531
+ - Example: `MyNamespace123` is valid
532
+
533
+ - Example: `_namespace` is not valid (starts with underscore)
534
+
535
+ **Cloudflare**:
536
+
537
+ Index names must:
538
+
539
+ - Start with a letter
540
+ - Be shorter than 32 characters
541
+ - Contain only lowercase ASCII letters, numbers, and dashes
542
+ - Use dashes instead of spaces
543
+ - Example: `my-index-123` is valid
544
+ - Example: `My_Index` is not valid (uppercase and underscore)
545
+
546
+ **OpenSearch**:
547
+
548
+ Index names must:
549
+
550
+ - Use only lowercase letters
551
+ - Not begin with underscores or hyphens
552
+ - Not contain spaces, commas
553
+ - Not contain special characters (e.g. `:`, `"`, `*`, `+`, `/`, `\`, `|`, `?`, `#`, `>`, `<`)
554
+ - Example: `my-index-123` is valid
555
+ - Example: `My_Index` is not valid (contains uppercase letters)
556
+ - Example: `_myindex` is not valid (begins with underscore)
557
+
558
+ **Elasticsearch**:
559
+
560
+ Index names must:
561
+
562
+ - Use only lowercase letters
563
+ - Not exceed 255 bytes (counting multi-byte characters)
564
+ - Not begin with underscores, hyphens, or plus signs
565
+ - Not contain spaces, commas
566
+ - Not contain special characters (e.g. `:`, `"`, `*`, `+`, `/`, `\`, `|`, `?`, `#`, `>`, `<`)
567
+ - Not be "." or ".."
568
+ - Not start with "." (deprecated except for system/hidden indices)
569
+ - Example: `my-index-123` is valid
570
+ - Example: `My_Index` is not valid (contains uppercase letters)
571
+ - Example: `_myindex` is not valid (begins with underscore)
572
+ - Example: `.myindex` is not valid (begins with dot, deprecated)
573
+
574
+ **S3 Vectors**:
575
+
576
+ Index names must:
577
+
578
+ - Be unique within the same vector bucket
579
+ - Be 3–63 characters long
580
+ - Use only lowercase letters (`a–z`), numbers (`0–9`), hyphens (`-`), and dots (`.`)
581
+ - Begin and end with a letter or number
582
+ - Example: `my-index.123` is valid
583
+ - Example: `my_index` is not valid (contains underscore)
584
+ - Example: `-myindex` is not valid (begins with hyphen)
585
+ - Example: `myindex-` is not valid (ends with hyphen)
586
+ - Example: `MyIndex` is not valid (contains uppercase letters)
587
+
588
+ ### Upserting Embeddings
589
+
590
+ After creating an index, you can store embeddings along with their basic metadata:
591
+
592
+ ```ts
593
+ // Store embeddings with their corresponding metadata
594
+ await store.upsert({
595
+ indexName: 'myCollection', // index name
596
+ vectors: embeddings, // array of embedding vectors
597
+ metadata: chunks.map(chunk => ({
598
+ text: chunk.text, // The original text content
599
+ id: chunk.id, // Optional unique identifier
600
+ })),
601
+ })
602
+ ```
603
+
604
+ The upsert operation:
605
+
606
+ - Takes an array of embedding vectors and their corresponding metadata
607
+ - Updates existing vectors if they share the same ID
608
+ - Creates new vectors if they don't exist
609
+ - Automatically handles batching for large datasets
610
+
611
+ ## Adding metadata
612
+
613
+ Vector stores support rich metadata (any JSON-serializable fields) for filtering and organization. Since metadata is stored with no fixed schema, use consistent field naming to avoid unexpected query results.
614
+
615
+ > **Warning:** Metadata is important for vector storage. Without it, you'd only have numerical embeddings with no way to return the original text or filter results. Always store at least the source text as metadata.
616
+
617
+ ```ts
618
+ // Store embeddings with rich metadata for better organization and filtering
619
+ await store.upsert({
620
+ indexName: 'myCollection',
621
+ vectors: embeddings,
622
+ metadata: chunks.map(chunk => ({
623
+ // Basic content
624
+ text: chunk.text,
625
+ id: chunk.id,
626
+
627
+ // Document organization
628
+ source: chunk.source,
629
+ category: chunk.category,
630
+
631
+ // Temporal metadata
632
+ createdAt: new Date().toISOString(),
633
+ version: '1.0',
634
+
635
+ // Custom fields
636
+ language: chunk.language,
637
+ author: chunk.author,
638
+ confidenceScore: chunk.score,
639
+ })),
640
+ })
641
+ ```
642
+
643
+ Key metadata considerations:
644
+
645
+ - Be strict with field naming - inconsistencies like 'category' vs 'Category' will affect queries
646
+ - Only include fields you plan to filter or sort by - extra fields add overhead
647
+ - Add timestamps (e.g., 'createdAt', 'lastUpdated') to track content freshness
648
+
649
+ ## Deleting vectors
650
+
651
+ When building RAG applications, you often need to clean up stale vectors when documents are deleted or updated. Mastra provides the `deleteVectors` method that supports deleting vectors by metadata filters, making it straightforward to remove all embeddings associated with a specific document.
652
+
653
+ ### Delete by Metadata Filter
654
+
655
+ The most common use case is deleting all vectors for a specific document when a user deletes it:
656
+
657
+ ```ts
658
+ // Delete all vectors for a specific document
659
+ await store.deleteVectors({
660
+ indexName: 'myCollection',
661
+ filter: { docId: 'document-123' },
662
+ })
663
+ ```
664
+
665
+ This is particularly useful when:
666
+
667
+ - A user deletes a document and you need to remove all its chunks
668
+ - You're re-indexing a document and want to remove old vectors first
669
+ - You need to clean up vectors for a specific user or tenant
670
+
671
+ ### Delete Multiple Documents
672
+
673
+ You can also use complex filters to delete vectors matching multiple conditions:
674
+
675
+ ```ts
676
+ // Delete all vectors for multiple documents
677
+ await store.deleteVectors({
678
+ indexName: 'myCollection',
679
+ filter: {
680
+ docId: { $in: ['doc-1', 'doc-2', 'doc-3'] },
681
+ },
682
+ })
683
+
684
+ // Delete vectors for a specific user's documents
685
+ await store.deleteVectors({
686
+ indexName: 'myCollection',
687
+ filter: {
688
+ $and: [{ userId: 'user-123' }, { status: 'archived' }],
689
+ },
690
+ })
691
+ ```
692
+
693
+ ### Delete by Vector IDs
694
+
695
+ If you have specific vector IDs to delete, you can pass them directly:
696
+
697
+ ```ts
698
+ // Delete specific vectors by their IDs
699
+ await store.deleteVectors({
700
+ indexName: 'myCollection',
701
+ ids: ['vec-1', 'vec-2', 'vec-3'],
702
+ })
703
+ ```
704
+
705
+ ## Best practices
706
+
707
+ - Create indexes before bulk insertions
708
+ - Use batch operations for large insertions (the upsert method handles batching automatically)
709
+ - Only store metadata you'll query against
710
+ - Match embedding dimensions to your model (e.g., 1536 for `text-embedding-3-small`)