|
| 1 | +# Azure Cosmos DB for MongoDB (vCore) - AI Vector Search Samples |
| 2 | + |
| 3 | +This directory contains vector search samples demonstrating how to use Azure Cosmos DB for MongoDB (vCore) with AI embeddings across multiple programming languages. |
| 4 | + |
| 5 | +## Available Samples |
| 6 | + |
| 7 | +- **vector-search-python** - Python implementation using PyMongo |
| 8 | +- **vector-search-typescript** - TypeScript implementation using Node.js MongoDB driver |
| 9 | +- **vector-search-go** - Go implementation using official MongoDB Go driver |
| 10 | +- **vector-search-java** - Java implementation using MongoDB Java Sync driver |
| 11 | +- **vector-search-dotnet** - .NET implementation using MongoDB C# driver |
| 12 | +- **vector-search-agent-ts** - TypeScript agent implementation using LangChain |
| 13 | +- **vector-search-agent-go** - Go agent implementation with vector store |
| 14 | + |
| 15 | +## MongoDB Bulk Insert Best Practices |
| 16 | + |
| 17 | +When creating new samples or modifying existing ones, always use the optimal bulk insert method for your language. This ensures best performance with parallel execution, automatic retry logic, and proper error handling. |
| 18 | + |
| 19 | +### Python (PyMongo 4.6.0+) |
| 20 | + |
| 21 | +**Required Driver:** `pymongo>=4.6.0` |
| 22 | + |
| 23 | +**Recommended Method:** |
| 24 | +```python |
| 25 | +from pymongo.operations import InsertOne |
| 26 | +from pymongo.errors import BulkWriteError |
| 27 | + |
| 28 | +# Process in batches |
| 29 | +for i in range(0, total_documents, batch_size): |
| 30 | + batch = data[i:i + batch_size] |
| 31 | + |
| 32 | + try: |
| 33 | + # Prepare bulk insert operations |
| 34 | + operations = [InsertOne(document) for document in batch] |
| 35 | + |
| 36 | + # Execute bulk insert with unordered flag |
| 37 | + result = collection.bulk_write(operations, ordered=False) |
| 38 | + inserted_count += result.inserted_count |
| 39 | + |
| 40 | + except BulkWriteError as e: |
| 41 | + # Handle partial failures |
| 42 | + inserted = len(batch) - len(e.details['writeErrors']) |
| 43 | + inserted_count += inserted |
| 44 | + failed_count += len(e.details['writeErrors']) |
| 45 | +``` |
| 46 | + |
| 47 | +**Alternative (simpler but less flexible):** |
| 48 | +```python |
| 49 | +result = collection.insert_many(documents, ordered=False) |
| 50 | +``` |
| 51 | + |
| 52 | +**Key Features:** |
| 53 | +- `ordered=False` enables parallel execution |
| 54 | +- Built-in retry logic for retryable errors |
| 55 | +- Continues on individual document failures |
| 56 | + |
| 57 | +### TypeScript/JavaScript (MongoDB Node.js Driver 6.0+) |
| 58 | + |
| 59 | +**Required Driver:** `mongodb@^6.0.0` |
| 60 | + |
| 61 | +**Recommended Method:** |
| 62 | +```typescript |
| 63 | +import { MongoClient } from 'mongodb'; |
| 64 | + |
| 65 | +// Process in batches |
| 66 | +for (let i = 0; i < totalBatches; i++) { |
| 67 | + const batch = data.slice(start, end); |
| 68 | + |
| 69 | + try { |
| 70 | + // Insert with unordered flag |
| 71 | + const result = await collection.insertMany(batch, { ordered: false }); |
| 72 | + inserted += result.insertedCount || 0; |
| 73 | + |
| 74 | + } catch (error: any) { |
| 75 | + // Handle bulk write errors |
| 76 | + if (error?.writeErrors) { |
| 77 | + failed += error.writeErrors.length; |
| 78 | + inserted += batch.length - error.writeErrors.length; |
| 79 | + } |
| 80 | + } |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +**Key Features:** |
| 85 | +- `ordered: false` enables parallel execution |
| 86 | +- Automatic retry for retryable writes |
| 87 | +- Tracks partial successes in error handling |
| 88 | + |
| 89 | +### Go (MongoDB Go Driver 1.17+) |
| 90 | + |
| 91 | +**Required Driver:** `go.mongodb.org/mongo-driver@v1.17.0` or later |
| 92 | + |
| 93 | +**Recommended Method:** |
| 94 | +```go |
| 95 | +import ( |
| 96 | + "context" |
| 97 | + "go.mongodb.org/mongo-driver/mongo" |
| 98 | + "go.mongodb.org/mongo-driver/mongo/options" |
| 99 | +) |
| 100 | + |
| 101 | +// Process in batches |
| 102 | +for i := 0; i < totalDocuments; i += batchSize { |
| 103 | + batch := data[i:end] |
| 104 | + |
| 105 | + // Convert to []interface{} for MongoDB driver |
| 106 | + documents := make([]interface{}, len(batch)) |
| 107 | + for j, doc := range batch { |
| 108 | + documents[j] = doc |
| 109 | + } |
| 110 | + |
| 111 | + // Insert with unordered option |
| 112 | + opts := options.InsertMany().SetOrdered(false) |
| 113 | + result, err := collection.InsertMany(ctx, documents, opts) |
| 114 | + |
| 115 | + if err != nil { |
| 116 | + // Handle bulk write errors |
| 117 | + if bulkErr, ok := err.(mongo.BulkWriteException); ok { |
| 118 | + inserted := len(batch) - len(bulkErr.WriteErrors) |
| 119 | + insertedCount += inserted |
| 120 | + failedCount += len(bulkErr.WriteErrors) |
| 121 | + } |
| 122 | + } else { |
| 123 | + insertedCount += len(result.InsertedIDs) |
| 124 | + } |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +**Key Features:** |
| 129 | +- `SetOrdered(false)` enables parallel execution |
| 130 | +- Automatic retry logic built into driver |
| 131 | +- Type assertion for handling bulk write exceptions |
| 132 | + |
| 133 | +### Java (MongoDB Java Sync Driver 5.0+) |
| 134 | + |
| 135 | +**Required Driver:** `mongodb-driver-sync@5.0.0` or later |
| 136 | + |
| 137 | +**Recommended Method:** |
| 138 | +```java |
| 139 | +import com.mongodb.client.MongoCollection; |
| 140 | +import com.mongodb.client.model.InsertManyOptions; |
| 141 | +import com.mongodb.MongoBulkWriteException; |
| 142 | +import org.bson.Document; |
| 143 | +import java.util.List; |
| 144 | + |
| 145 | +// Process in batches |
| 146 | +int totalInserted = 0; |
| 147 | +int totalFailed = 0; |
| 148 | + |
| 149 | +for (int i = 0; i < batches.size(); i++) { |
| 150 | + List<Document> batch = batches.get(i); |
| 151 | + |
| 152 | + // Create options with unordered flag |
| 153 | + InsertManyOptions insertOptions = new InsertManyOptions().ordered(false); |
| 154 | + |
| 155 | + try { |
| 156 | + collection.insertMany(batch, insertOptions); |
| 157 | + totalInserted += batch.size(); |
| 158 | + |
| 159 | + } catch (MongoBulkWriteException e) { |
| 160 | + // Handle partial failures |
| 161 | + int inserted = batch.size() - e.getWriteErrors().size(); |
| 162 | + totalInserted += inserted; |
| 163 | + totalFailed += e.getWriteErrors().size(); |
| 164 | + } |
| 165 | +} |
| 166 | +``` |
| 167 | + |
| 168 | +**Key Features:** |
| 169 | +- `ordered(false)` enables parallel execution |
| 170 | +- Exception handling for partial successes |
| 171 | +- Built-in retry mechanism in driver |
| 172 | + |
| 173 | +### .NET (MongoDB C# Driver 2.19+) |
| 174 | + |
| 175 | +**Required Driver:** `MongoDB.Driver@2.19.0` or later (3.0.0+ recommended) |
| 176 | + |
| 177 | +**Recommended Method:** |
| 178 | +```csharp |
| 179 | +using MongoDB.Driver; |
| 180 | +using System.Collections.Generic; |
| 181 | +using System.Threading.Tasks; |
| 182 | + |
| 183 | +// Process all documents |
| 184 | +var dataList = data.ToList(); |
| 185 | + |
| 186 | +try |
| 187 | +{ |
| 188 | + // Use unordered insert for better performance |
| 189 | + var options = new InsertManyOptions { IsOrdered = false }; |
| 190 | + await collection.InsertManyAsync(dataList, options); |
| 191 | + inserted = dataList.Count; |
| 192 | +} |
| 193 | +catch (MongoBulkWriteException ex) |
| 194 | +{ |
| 195 | + // Handle partial failures |
| 196 | + // Note: Track success/failure based on exception details |
| 197 | + failed = ex.WriteErrors.Count; |
| 198 | + inserted = dataList.Count - failed; |
| 199 | +} |
| 200 | +``` |
| 201 | + |
| 202 | +**Key Features:** |
| 203 | +- `IsOrdered = false` enables parallel execution |
| 204 | +- Async/await pattern for better performance |
| 205 | +- Automatic retry for transient failures |
| 206 | + |
| 207 | +### LangChain Integration (TypeScript) |
| 208 | + |
| 209 | +**Required Package:** `@langchain/azure-cosmosdb@^1.0.0` |
| 210 | + |
| 211 | +**Recommended Method:** |
| 212 | +```typescript |
| 213 | +import { AzureCosmosDBMongoDBVectorStore } from '@langchain/azure-cosmosdb'; |
| 214 | +import { Document } from '@langchain/core/documents'; |
| 215 | + |
| 216 | +// Prepare documents |
| 217 | +const documents = data.map(item => new Document({ |
| 218 | + pageContent: `${item.title}\n\n${item.description}`, |
| 219 | + metadata: item, |
| 220 | + id: item.id.toString() |
| 221 | +})); |
| 222 | + |
| 223 | +// Insert using LangChain abstraction |
| 224 | +const store = await AzureCosmosDBMongoDBVectorStore.fromDocuments( |
| 225 | + documents, |
| 226 | + embeddingClient, |
| 227 | + { |
| 228 | + ...dbConfig, |
| 229 | + indexOptions: vectorIndexOptions, |
| 230 | + } |
| 231 | +); |
| 232 | +``` |
| 233 | + |
| 234 | +**Key Features:** |
| 235 | +- Abstracts bulk insert complexity |
| 236 | +- Uses optimal MongoDB settings internally |
| 237 | +- Handles vector index creation |
| 238 | + |
| 239 | +## General Guidelines for All Languages |
| 240 | + |
| 241 | +1. **Always use unordered inserts** (`ordered=false` or equivalent) for bulk operations |
| 242 | + - Enables parallel execution across shards |
| 243 | + - Continues processing even if individual documents fail |
| 244 | + - Significantly improves throughput |
| 245 | + |
| 246 | +2. **Implement proper error handling** |
| 247 | + - Catch bulk write exceptions |
| 248 | + - Track both successful and failed insertions |
| 249 | + - Log partial successes for observability |
| 250 | + |
| 251 | +3. **Process in batches** |
| 252 | + - Typical batch size: 100-1000 documents |
| 253 | + - Adjust based on document size and memory constraints |
| 254 | + - Provide progress feedback during insertion |
| 255 | + |
| 256 | +4. **Leverage driver features** |
| 257 | + - Use the latest stable driver version |
| 258 | + - Automatic retry logic is built into modern drivers |
| 259 | + - Connection pooling is configured by default |
| 260 | + |
| 261 | +5. **Create indexes after insertion** |
| 262 | + - Insert data first, then create standard indexes |
| 263 | + - Create vector indexes using database commands |
| 264 | + - Reduces overhead during bulk operations |
| 265 | + |
| 266 | +## MongoDB Driver Versions |
| 267 | + |
| 268 | +| Language | Driver | Minimum Version | Recommended | |
| 269 | +|----------|--------|----------------|-------------| |
| 270 | +| Python | pymongo | 4.6.0 | Latest 4.x | |
| 271 | +| TypeScript/JavaScript | mongodb | 6.0.0 | Latest 6.x | |
| 272 | +| Go | mongo-driver | 1.17.0 | Latest 1.x | |
| 273 | +| Java | mongodb-driver-sync | 5.0.0 | Latest 5.x | |
| 274 | +| .NET | MongoDB.Driver | 2.19.0 | Latest 3.x | |
| 275 | + |
| 276 | +## Additional Resources |
| 277 | + |
| 278 | +- **Detailed Analysis:** See [BULK_OPERATION_ANALYSIS.md](./BULK_OPERATION_ANALYSIS.md) for comprehensive analysis of all samples |
| 279 | +- **MongoDB Documentation:** [Bulk Write Operations](https://docs.mongodb.com/manual/core/bulk-write-operations/) |
| 280 | +- **Vector Search:** [Azure Cosmos DB for MongoDB (vCore) Vector Search](https://learn.microsoft.com/azure/cosmos-db/mongodb/vcore/vector-search) |
| 281 | + |
| 282 | +## Performance Tips |
| 283 | + |
| 284 | +1. **Connection Pooling:** Configure appropriate pool sizes for your workload |
| 285 | +2. **Write Concern:** Use `w: 1` for better performance in non-critical scenarios |
| 286 | +3. **Batch Size:** Experiment with batch sizes (100-1000) to find optimal throughput |
| 287 | +4. **Network Latency:** Deploy applications in the same region as your database |
| 288 | +5. **Index Strategy:** Create indexes after bulk insert completes |
| 289 | + |
| 290 | +## Contributing |
| 291 | + |
| 292 | +When contributing new samples: |
| 293 | +1. Follow the bulk insert patterns documented above for your language |
| 294 | +2. Include comprehensive error handling |
| 295 | +3. Add logging for observability |
| 296 | +4. Test with both successful and failure scenarios |
| 297 | +5. Update this README if introducing new patterns or languages |
0 commit comments