insert-many
Insert multiple documents into a MongoDB collection using an array of data. Specify the database, collection, and documents to streamline bulk data insertion processes.
Instructions
Insert an array of documents into a MongoDB collection
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| collection | Yes | Collection name | |
| database | Yes | Database name | |
| documents | Yes | The array of documents to insert, matching the syntax of the document argument of db.collection.insertMany() |
Implementation Reference
- The main handler function that executes the 'insert-many' tool. It connects to the provider, processes embeddings if provided, validates embeddings, performs the insertMany operation, and formats the result.protected async execute({ database, collection, documents, ...conditionalArgs }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> { const provider = await this.ensureConnected(); let embeddingParameters: z.infer<typeof zSupportedEmbeddingParametersWithInput> | undefined; if ("embeddingParameters" in conditionalArgs) { embeddingParameters = conditionalArgs.embeddingParameters; } // Process documents to replace raw string values with generated embeddings documents = await this.replaceRawValuesWithEmbeddingsIfNecessary({ database, collection, documents, embeddingParameters, }); await this.session.vectorSearchEmbeddingsManager.assertFieldsHaveCorrectEmbeddings( { database, collection }, documents ); const result = await provider.insertMany(database, collection, documents); const content = formatUntrustedData( "Documents were inserted successfully.", `Inserted \`${result.insertedCount}\` document(s) into ${database}.${collection}.`, `Inserted IDs: ${Object.values(result.insertedIds).join(", ")}` ); return { content, }; }
- Defines the Zod schemas for tool arguments: commonArgs (including documents), embedding parameters, and the full argsShape which conditionally includes embeddingParameters based on search feature.const zSupportedEmbeddingParametersWithInput = zSupportedEmbeddingParameters.extend({ input: z .array(z.object({}).passthrough()) .describe( "Array of objects with vector search index fields as keys (in dot notation) and the raw text values to generate embeddings for as values. The index of each object corresponds to the index of the document in the documents array." ), }); const commonArgs = { ...DbOperationArgs, documents: z .array(zEJSON().describe("An individual MongoDB document")) .describe( "The array of documents to insert, matching the syntax of the document argument of db.collection.insertMany()." ), } as const; export class InsertManyTool extends MongoDBToolBase { public name = "insert-many"; protected description = "Insert an array of documents into a MongoDB collection"; protected argsShape = this.isFeatureEnabled("search") ? { ...commonArgs, embeddingParameters: zSupportedEmbeddingParametersWithInput .optional() .describe( "The embedding model and its parameters to use to generate embeddings for fields with vector search indexes. Note to LLM: If unsure which embedding model to use, ask the user before providing one." ), } : commonArgs;
- src/tools/mongodb/create/insertMany.ts:27-30 (registration)The InsertManyTool class definition where the tool name 'insert-many' is registered and description is set.export class InsertManyTool extends MongoDBToolBase { public name = "insert-many"; protected description = "Insert an array of documents into a MongoDB collection"; protected argsShape = this.isFeatureEnabled("search")
- Helper method to generate and replace raw text values with embeddings in documents for vector search index fields.private async replaceRawValuesWithEmbeddingsIfNecessary({ database, collection, documents, embeddingParameters, }: { database: string; collection: string; documents: Document[]; embeddingParameters?: z.infer<typeof zSupportedEmbeddingParametersWithInput>; }): Promise<Document[]> { // If no embedding parameters or no input specified, return documents as-is if (!embeddingParameters?.input || embeddingParameters.input.length === 0) { return documents; } // Get vector search indexes for the collection const vectorIndexes = await this.session.vectorSearchEmbeddingsManager.embeddingsForNamespace({ database, collection, }); // Ensure for inputted fields, the vector search index exists. for (const input of embeddingParameters.input) { for (const fieldPath of Object.keys(input)) { if (!vectorIndexes.some((index) => index.path === fieldPath)) { throw new MongoDBError( ErrorCodes.AtlasVectorSearchInvalidQuery, `Field '${fieldPath}' does not have a vector search index in collection ${database}.${collection}. Only fields with vector search indexes can have embeddings generated.` ); } } } // We make one call to generate embeddings for all documents at once to avoid making too many API calls. const flattenedEmbeddingsInput = embeddingParameters.input.flatMap((documentInput, index) => Object.entries(documentInput).map(([fieldPath, rawTextValue]) => ({ fieldPath, rawTextValue, documentIndex: index, })) ); const generatedEmbeddings = await this.session.vectorSearchEmbeddingsManager.generateEmbeddings({ rawValues: flattenedEmbeddingsInput.map(({ rawTextValue }) => rawTextValue) as string[], embeddingParameters, inputType: "document", }); const processedDocuments: Document[] = [...documents]; for (const [index, { fieldPath, documentIndex }] of flattenedEmbeddingsInput.entries()) { if (!processedDocuments[documentIndex]) { throw new MongoDBError(ErrorCodes.Unexpected, `Document at index ${documentIndex} does not exist.`); } // Ensure no nested fields are present in the field path. this.deleteFieldPath(processedDocuments[documentIndex], fieldPath); processedDocuments[documentIndex][fieldPath] = generatedEmbeddings[index]; } return processedDocuments; }
- Utility method to delete a field from a document using dot notation path.// Delete a specified field path from a document using dot notation. private deleteFieldPath(document: Record<string, unknown>, fieldPath: string): void { const parts = fieldPath.split("."); let current: Record<string, unknown> = document; for (let i = 0; i < parts.length; i++) { const part = parts[i]; const key = part as keyof typeof current; if (!current[key]) { return; } else if (i === parts.length - 1) { delete current[key]; } else { current = current[key] as Record<string, unknown>; } } }