@mastra/mongodb 1.5.1 → 1.5.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.
@@ -0,0 +1,262 @@
1
+ # MongoDB Storage
2
+
3
+ The MongoDB storage implementation provides a scalable storage solution using MongoDB databases with support for both document storage and vector operations.
4
+
5
+ ## Installation
6
+
7
+ **npm**:
8
+
9
+ ```bash
10
+ npm install @mastra/mongodb@latest
11
+ ```
12
+
13
+ **pnpm**:
14
+
15
+ ```bash
16
+ pnpm add @mastra/mongodb@latest
17
+ ```
18
+
19
+ **Yarn**:
20
+
21
+ ```bash
22
+ yarn add @mastra/mongodb@latest
23
+ ```
24
+
25
+ **Bun**:
26
+
27
+ ```bash
28
+ bun add @mastra/mongodb@latest
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ Ensure you have a MongoDB Atlas Local (via Docker) or MongoDB Atlas Cloud instance with Atlas Search enabled. MongoDB 7.0+ is recommended.
34
+
35
+ ```typescript
36
+ import { MongoDBStore } from '@mastra/mongodb'
37
+
38
+ const storage = new MongoDBStore({
39
+ id: 'mongodb-storage',
40
+ uri: process.env.MONGODB_URI,
41
+ dbName: process.env.MONGODB_DATABASE,
42
+ })
43
+ ```
44
+
45
+ ## Parameters
46
+
47
+ **id:** (`string`): Unique identifier for this storage instance.
48
+
49
+ **uri:** (`string`): MongoDB connection string (e.g., mongodb+srv://user:password\@cluster.mongodb.net)
50
+
51
+ **url?:** (`string`): Deprecated. Use uri instead. MongoDB connection string (supported for backward compatibility).
52
+
53
+ **dbName:** (`string`): The name of the database you want the storage to use.
54
+
55
+ **options?:** (`MongoClientOptions`): MongoDB client options for advanced configuration (SSL, connection pooling, etc.).
56
+
57
+ > **Deprecation Notice:** The `url` parameter is deprecated but still supported for backward compatibility. Please use `uri` instead in all new code.
58
+
59
+ ## Constructor Examples
60
+
61
+ You can instantiate `MongoDBStore` in the following ways:
62
+
63
+ ```ts
64
+ import { MongoDBStore } from '@mastra/mongodb'
65
+
66
+ // Basic connection without custom options
67
+ const store1 = new MongoDBStore({
68
+ id: 'mongodb-storage-01',
69
+ uri: 'mongodb+srv://user:password@cluster.mongodb.net',
70
+ dbName: 'mastra_storage',
71
+ })
72
+
73
+ // Using connection string with options
74
+ const store2 = new MongoDBStore({
75
+ id: 'mongodb-storage-02',
76
+ uri: 'mongodb+srv://user:password@cluster.mongodb.net',
77
+ dbName: 'mastra_storage',
78
+ options: {
79
+ retryWrites: true,
80
+ maxPoolSize: 10,
81
+ serverSelectionTimeoutMS: 5000,
82
+ socketTimeoutMS: 45000,
83
+ },
84
+ })
85
+ ```
86
+
87
+ ## Additional Notes
88
+
89
+ ### Collection Management
90
+
91
+ The storage implementation handles collection creation and management automatically. It creates the following collections:
92
+
93
+ - `mastra_workflow_snapshot`: Stores workflow state and execution data
94
+ - `mastra_evals`: Stores evaluation results and metadata
95
+ - `mastra_threads`: Stores conversation threads
96
+ - `mastra_messages`: Stores individual messages
97
+ - `mastra_traces`: Stores telemetry and tracing data
98
+ - `mastra_scorers`: Stores scoring and evaluation data
99
+ - `mastra_resources`: Stores resource working memory data
100
+
101
+ ### Initialization
102
+
103
+ When you pass storage to the Mastra class, `init()` is called automatically before any storage operation:
104
+
105
+ ```typescript
106
+ import { Mastra } from '@mastra/core'
107
+ import { MongoDBStore } from '@mastra/mongodb'
108
+
109
+ const storage = new MongoDBStore({
110
+ id: 'mongodb-storage',
111
+ uri: process.env.MONGODB_URI,
112
+ dbName: process.env.MONGODB_DATABASE,
113
+ })
114
+
115
+ const mastra = new Mastra({
116
+ storage, // init() is called automatically
117
+ })
118
+ ```
119
+
120
+ If you're using storage directly without Mastra, you must call `init()` explicitly to create the collections:
121
+
122
+ ```typescript
123
+ import { MongoDBStore } from '@mastra/mongodb'
124
+
125
+ const storage = new MongoDBStore({
126
+ id: 'mongodb-storage',
127
+ uri: process.env.MONGODB_URI,
128
+ dbName: process.env.MONGODB_DATABASE,
129
+ })
130
+
131
+ // Required when using storage directly
132
+ await storage.init()
133
+
134
+ // Access domain-specific stores via getStore()
135
+ const memoryStore = await storage.getStore('memory')
136
+ const thread = await memoryStore?.getThreadById({ threadId: '...' })
137
+ ```
138
+
139
+ > **Warning:** If `init()` is not called, collections won't be created and storage operations will fail silently or throw errors.
140
+
141
+ ## Vector Search Capabilities
142
+
143
+ MongoDB storage includes built-in vector search capabilities for AI applications:
144
+
145
+ ### Vector Index Creation
146
+
147
+ ```typescript
148
+ import { MongoDBVector } from '@mastra/mongodb'
149
+
150
+ const vectorStore = new MongoDBVector({
151
+ id: 'mongodb-vector',
152
+ uri: process.env.MONGODB_URI,
153
+ dbName: process.env.MONGODB_DATABASE,
154
+ })
155
+
156
+ // Create a vector index for embeddings
157
+ await vectorStore.createIndex({
158
+ indexName: 'document_embeddings',
159
+ dimension: 1536,
160
+ })
161
+ ```
162
+
163
+ ### Vector Operations
164
+
165
+ ```typescript
166
+ // Store vectors with metadata
167
+ await vectorStore.upsert({
168
+ indexName: "document_embeddings",
169
+ vectors: [
170
+ {
171
+ id: "doc-1",
172
+ values: [0.1, 0.2, 0.3, ...], // 1536-dimensional vector
173
+ metadata: {
174
+ title: "Document Title",
175
+ category: "technical",
176
+ source: "api-docs",
177
+ },
178
+ },
179
+ ],
180
+ });
181
+
182
+ // Similarity search
183
+ const results = await vectorStore.query({
184
+ indexName: "document_embeddings",
185
+ vector: queryEmbedding,
186
+ topK: 5,
187
+ filter: {
188
+ category: "technical",
189
+ },
190
+ });
191
+ ```
192
+
193
+ ## Usage Example
194
+
195
+ ### Adding memory to an agent
196
+
197
+ To add MongoDB memory to an agent use the `Memory` class and create a new `storage` key using `MongoDBStore`. The configuration supports both local and remote MongoDB instances.
198
+
199
+ ```typescript
200
+ import { Memory } from '@mastra/memory'
201
+ import { Agent } from '@mastra/core/agent'
202
+ import { MongoDBStore } from '@mastra/mongodb'
203
+
204
+ export const mongodbAgent = new Agent({
205
+ id: 'mongodb-agent',
206
+ name: 'mongodb-agent',
207
+ instructions:
208
+ 'You are an AI agent with the ability to automatically recall memories from previous interactions.',
209
+ model: 'openai/gpt-5.1',
210
+ memory: new Memory({
211
+ storage: new MongoDBStore({
212
+ uri: process.env.MONGODB_URI!,
213
+ dbName: process.env.MONGODB_DB_NAME!,
214
+ }),
215
+ options: {
216
+ generateTitle: true,
217
+ },
218
+ }),
219
+ })
220
+ ```
221
+
222
+ ### Using the agent
223
+
224
+ Use `memoryOptions` to scope recall for this request. Set `lastMessages: 5` to limit recency-based recall, and use `semanticRecall` to fetch the `topK: 3` most relevant messages, including `messageRange: 2` neighboring messages for context around each match.
225
+
226
+ ```typescript
227
+ import 'dotenv/config'
228
+
229
+ import { mastra } from './mastra'
230
+
231
+ const threadId = '123'
232
+ const resourceId = 'user-456'
233
+
234
+ const agent = mastra.getAgent('mongodbAgent')
235
+
236
+ const message = await agent.stream('My name is Mastra', {
237
+ memory: {
238
+ thread: threadId,
239
+ resource: resourceId,
240
+ },
241
+ })
242
+
243
+ await message.textStream.pipeTo(new WritableStream())
244
+
245
+ const stream = await agent.stream("What's my name?", {
246
+ memory: {
247
+ thread: threadId,
248
+ resource: resourceId,
249
+ },
250
+ memoryOptions: {
251
+ lastMessages: 5,
252
+ semanticRecall: {
253
+ topK: 3,
254
+ messageRange: 2,
255
+ },
256
+ },
257
+ })
258
+
259
+ for await (const chunk of stream.textStream) {
260
+ process.stdout.write(chunk)
261
+ }
262
+ ```
@@ -0,0 +1,295 @@
1
+ # MongoDB Vector Store
2
+
3
+ The `MongoDBVector` class provides vector search using [MongoDB Atlas Vector Search](https://www.mongodb.com/docs/atlas/atlas-vector-search/). It enables efficient similarity search and metadata filtering within your MongoDB collections.
4
+
5
+ ## Installation
6
+
7
+ **npm**:
8
+
9
+ ```bash
10
+ npm install @mastra/mongodb@latest
11
+ ```
12
+
13
+ **pnpm**:
14
+
15
+ ```bash
16
+ pnpm add @mastra/mongodb@latest
17
+ ```
18
+
19
+ **Yarn**:
20
+
21
+ ```bash
22
+ yarn add @mastra/mongodb@latest
23
+ ```
24
+
25
+ **Bun**:
26
+
27
+ ```bash
28
+ bun add @mastra/mongodb@latest
29
+ ```
30
+
31
+ ## Usage Example
32
+
33
+ ```typescript
34
+ import { MongoDBVector } from '@mastra/mongodb'
35
+
36
+ const store = new MongoDBVector({
37
+ id: 'mongodb-vector',
38
+ uri: process.env.MONGODB_URI,
39
+ dbName: process.env.MONGODB_DATABASE,
40
+ })
41
+ ```
42
+
43
+ ### Custom Embedding Field Path
44
+
45
+ If you need to store embeddings in a nested field structure (e.g., to integrate with existing MongoDB collections), use the `embeddingFieldPath` option:
46
+
47
+ ```typescript
48
+ import { MongoDBVector } from '@mastra/mongodb'
49
+
50
+ const store = new MongoDBVector({
51
+ id: 'mongodb-vector',
52
+ uri: process.env.MONGODB_URI,
53
+ dbName: process.env.MONGODB_DATABASE,
54
+ embeddingFieldPath: 'text.contentEmbedding', // Store embeddings at text.contentEmbedding
55
+ })
56
+ ```
57
+
58
+ ## Constructor Options
59
+
60
+ **id:** (`string`): Unique identifier for this vector store instance
61
+
62
+ **uri:** (`string`): MongoDB connection string
63
+
64
+ **dbName:** (`string`): Name of the MongoDB database to use
65
+
66
+ **options?:** (`MongoClientOptions`): Optional MongoDB client options
67
+
68
+ **embeddingFieldPath?:** (`string`): Path to the field that stores vector embeddings. Supports nested paths using dot notation (e.g., 'text.contentEmbedding'). (Default: `embedding`)
69
+
70
+ ## Methods
71
+
72
+ ### createIndex()
73
+
74
+ Creates a new vector index (collection) in MongoDB.
75
+
76
+ **indexName:** (`string`): Name of the collection to create
77
+
78
+ **dimension:** (`number`): Vector dimension (must match your embedding model)
79
+
80
+ **metric?:** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`)
81
+
82
+ ### upsert()
83
+
84
+ Adds or updates vectors and their metadata in the collection.
85
+
86
+ **indexName:** (`string`): Name of the collection to insert into
87
+
88
+ **vectors:** (`number[][]`): Array of embedding vectors
89
+
90
+ **metadata?:** (`Record<string, any>[]`): Metadata for each vector
91
+
92
+ **ids?:** (`string[]`): Optional vector IDs (auto-generated if not provided)
93
+
94
+ ### query()
95
+
96
+ Searches for similar vectors with optional metadata filtering.
97
+
98
+ **indexName:** (`string`): Name of the collection to search in
99
+
100
+ **queryVector:** (`number[]`): Query vector to find similar vectors for
101
+
102
+ **topK?:** (`number`): Number of results to return (Default: `10`)
103
+
104
+ **filter?:** (`Record<string, any>`): Metadata filters (applies to the \`metadata\` field)
105
+
106
+ **documentFilter?:** (`Record<string, any>`): Filters on original document fields (not just metadata)
107
+
108
+ **includeVector?:** (`boolean`): Whether to include vector data in results (Default: `false`)
109
+
110
+ **minScore?:** (`number`): Minimum similarity score threshold (Default: `0`)
111
+
112
+ ### describeIndex()
113
+
114
+ Returns information about the index (collection).
115
+
116
+ **indexName:** (`string`): Name of the collection to describe
117
+
118
+ Returns:
119
+
120
+ ```typescript
121
+ interface IndexStats {
122
+ dimension: number
123
+ count: number
124
+ metric: 'cosine' | 'euclidean' | 'dotproduct'
125
+ }
126
+ ```
127
+
128
+ ### deleteIndex()
129
+
130
+ Deletes a collection and all its data.
131
+
132
+ **indexName:** (`string`): Name of the collection to delete
133
+
134
+ ### listIndexes()
135
+
136
+ Lists all vector collections in the MongoDB database.
137
+
138
+ Returns: `Promise<string[]>`
139
+
140
+ ### updateVector()
141
+
142
+ Update a single vector by ID or by metadata filter. Either `id` or `filter` must be provided, but not both.
143
+
144
+ **indexName:** (`string`): Name of the collection containing the vector
145
+
146
+ **id?:** (`string`): ID of the vector entry to update (mutually exclusive with filter)
147
+
148
+ **filter?:** (`Record<string, any>`): Metadata filter to identify vector(s) to update (mutually exclusive with id)
149
+
150
+ **update:** (`object`): Update data containing vector and/or metadata
151
+
152
+ **update.vector?:** (`number[]`): New vector data to update
153
+
154
+ **update.metadata?:** (`Record<string, any>`): New metadata to update
155
+
156
+ ### deleteVector()
157
+
158
+ Deletes a specific vector entry from an index by its ID.
159
+
160
+ **indexName:** (`string`): Name of the collection containing the vector
161
+
162
+ **id:** (`string`): ID of the vector entry to delete
163
+
164
+ ### deleteVectors()
165
+
166
+ Delete multiple vectors by IDs or by metadata filter. Either `ids` or `filter` must be provided, but not both.
167
+
168
+ **indexName:** (`string`): Name of the collection containing the vectors to delete
169
+
170
+ **ids?:** (`string[]`): Array of vector IDs to delete (mutually exclusive with filter)
171
+
172
+ **filter?:** (`Record<string, any>`): Metadata filter to identify vectors to delete (mutually exclusive with ids)
173
+
174
+ ### disconnect()
175
+
176
+ Closes the MongoDB client connection. Should be called when done using the store.
177
+
178
+ ## Response Types
179
+
180
+ Query results are returned in this format:
181
+
182
+ ```typescript
183
+ interface QueryResult {
184
+ id: string
185
+ score: number
186
+ metadata: Record<string, any>
187
+ vector?: number[] // Only included if includeVector is true
188
+ }
189
+ ```
190
+
191
+ ## Error Handling
192
+
193
+ The store throws typed errors that can be caught:
194
+
195
+ ```typescript
196
+ try {
197
+ await store.query({
198
+ indexName: 'my_collection',
199
+ queryVector: queryVector,
200
+ })
201
+ } catch (error) {
202
+ // Handle specific error cases
203
+ if (error.message.includes('Invalid collection name')) {
204
+ console.error(
205
+ 'Collection name must start with a letter or underscore and contain only valid characters.',
206
+ )
207
+ } else if (error.message.includes('Collection not found')) {
208
+ console.error('The specified collection does not exist')
209
+ } else {
210
+ console.error('Vector store error:', error.message)
211
+ }
212
+ }
213
+ ```
214
+
215
+ ## Best Practices
216
+
217
+ - Index metadata fields used in filters for optimal query performance.
218
+ - Use consistent field naming in metadata to avoid unexpected query results.
219
+ - Regularly monitor index and collection statistics to ensure efficient search.
220
+
221
+ ## Usage Example
222
+
223
+ ### Vector embeddings with MongoDB
224
+
225
+ Embeddings are numeric vectors used by memory's `semanticRecall` to retrieve related messages by meaning (not keywords).
226
+
227
+ > **Note:** You must use a deployment hosted on MongoDB Atlas to successfully use the MongoDB Vector database.
228
+
229
+ This setup uses FastEmbed, a local embedding model, to generate vector embeddings. To use this, install `@mastra/fastembed`:
230
+
231
+ **npm**:
232
+
233
+ ```bash
234
+ npm install @mastra/fastembed@latest
235
+ ```
236
+
237
+ **pnpm**:
238
+
239
+ ```bash
240
+ pnpm add @mastra/fastembed@latest
241
+ ```
242
+
243
+ **Yarn**:
244
+
245
+ ```bash
246
+ yarn add @mastra/fastembed@latest
247
+ ```
248
+
249
+ **Bun**:
250
+
251
+ ```bash
252
+ bun add @mastra/fastembed@latest
253
+ ```
254
+
255
+ Add the following to your agent:
256
+
257
+ ```typescript
258
+ import { Memory } from '@mastra/memory'
259
+ import { Agent } from '@mastra/core/agent'
260
+ import { MongoDBStore, MongoDBVector } from '@mastra/mongodb'
261
+ import { fastembed } from '@mastra/fastembed'
262
+
263
+ export const mongodbAgent = new Agent({
264
+ id: 'mongodb-agent',
265
+ name: 'mongodb-agent',
266
+ instructions:
267
+ 'You are an AI agent with the ability to automatically recall memories from previous interactions.',
268
+ model: 'openai/gpt-5.1',
269
+ memory: new Memory({
270
+ storage: new MongoDBStore({
271
+ id: 'mongodb-storage',
272
+ uri: process.env.MONGODB_URI!,
273
+ dbName: process.env.MONGODB_DB_NAME!,
274
+ }),
275
+ vector: new MongoDBVector({
276
+ id: 'mongodb-vector',
277
+ uri: process.env.MONGODB_URI!,
278
+ dbName: process.env.MONGODB_DB_NAME!,
279
+ }),
280
+ embedder: fastembed,
281
+ options: {
282
+ lastMessages: 10,
283
+ semanticRecall: {
284
+ topK: 3,
285
+ messageRange: 2,
286
+ },
287
+ generateTitle: true, // generates descriptive thread titles automatically
288
+ },
289
+ }),
290
+ })
291
+ ```
292
+
293
+ ## Related
294
+
295
+ - [Metadata Filters](https://mastra.ai/reference/rag/metadata-filters)
package/dist/index.cjs CHANGED
@@ -14,7 +14,7 @@ var evals = require('@mastra/core/evals');
14
14
 
15
15
  // package.json
16
16
  var package_default = {
17
- version: "1.5.1"};
17
+ version: "1.5.2-alpha.0"};
18
18
  var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
19
19
  getSupportedOperators() {
20
20
  return {
@@ -340,6 +340,15 @@ var MongoDBVector = class extends vector.MastraVector {
340
340
  includeVector = false,
341
341
  documentFilter
342
342
  }) {
343
+ if (!queryVector) {
344
+ throw new error.MastraError({
345
+ id: storage.createVectorErrorId("MONGODB", "QUERY", "MISSING_VECTOR"),
346
+ text: "queryVector is required for MongoDB queries. Metadata-only queries are not supported by this vector store.",
347
+ domain: error.ErrorDomain.STORAGE,
348
+ category: error.ErrorCategory.USER,
349
+ details: { indexName }
350
+ });
351
+ }
343
352
  try {
344
353
  const collection = await this.getCollection(indexName, true);
345
354
  const indexNameInternal = `${indexName}_vector_index`;
@@ -4179,12 +4188,14 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemorySto
4179
4188
  const maxOvershoot = retentionFloor * 0.95;
4180
4189
  const overshoot = bestOverTokens - targetMessageTokens;
4181
4190
  const remainingAfterOver = input.currentPendingTokens - bestOverTokens;
4191
+ const remainingAfterUnder = input.currentPendingTokens - bestUnderTokens;
4192
+ const minRemaining = Math.min(1e3, retentionFloor);
4182
4193
  let chunksToActivate;
4183
- if (input.forceMaxActivation && bestOverBoundary > 0) {
4194
+ if (input.forceMaxActivation && bestOverBoundary > 0 && remainingAfterOver >= minRemaining) {
4184
4195
  chunksToActivate = bestOverBoundary;
4185
- } else if (bestOverBoundary > 0 && overshoot <= maxOvershoot && (remainingAfterOver >= 1e3 || retentionFloor === 0)) {
4196
+ } else if (bestOverBoundary > 0 && overshoot <= maxOvershoot && remainingAfterOver >= minRemaining) {
4186
4197
  chunksToActivate = bestOverBoundary;
4187
- } else if (bestUnderBoundary > 0) {
4198
+ } else if (bestUnderBoundary > 0 && remainingAfterUnder >= minRemaining) {
4188
4199
  chunksToActivate = bestUnderBoundary;
4189
4200
  } else if (bestOverBoundary > 0) {
4190
4201
  chunksToActivate = bestOverBoundary;