UNPKG

voyageai-cli

Version:

CLI for Voyage AI embeddings, reranking, and MongoDB Atlas Vector Search

301 lines (228 loc) 7.74 kB
# Indexes Indexes in MongoDB improve query performance by allowing the database to locate documents without scanning every document in a collection. Proper indexing is critical for production workloads. ## Single Field Index The most basic index type, created on a single field. ```javascript // Ascending index on email db.users.createIndex({ email: 1 }) // Descending index on createdAt db.users.createIndex({ createdAt: -1 }) // Verify the index was created db.users.getIndexes() ``` ## Unique Index Enforce uniqueness on a field. Rejects duplicate values. ```javascript db.users.createIndex({ email: 1 }, { unique: true }) // Unique compound index db.inventory.createIndex({ warehouse: 1, sku: 1 }, { unique: true }) // Attempting a duplicate insert will throw an error db.users.insertOne({ email: "ada@example.com" }) db.users.insertOne({ email: "ada@example.com" }) // MongoServerError: E11000 duplicate key error ``` ## Compound Index An index on multiple fields. Field order matters for query optimization. ```javascript db.orders.createIndex({ customerId: 1, orderDate: -1 }) // This index supports queries on: // - { customerId: ... } (prefix) // - { customerId: ..., orderDate: ... } (full match) // - { customerId: ... } sorted by orderDate (sort) // It does NOT efficiently support: // - { orderDate: ... } alone (not a prefix) ``` ## Multikey Index (Array Fields) MongoDB automatically creates a multikey index when you index a field that contains an array. Each array element gets an index entry. ```javascript db.articles.createIndex({ tags: 1 }) // Efficiently query any element in the array db.articles.find({ tags: "mongodb" }) db.articles.find({ tags: { $in: ["mongodb", "nosql"] } }) ``` ## Text Index Full-text search index for string content. One text index per collection. ```javascript db.articles.createIndex({ title: "text", body: "text", tags: "text" }, { weights: { title: 10, body: 5, tags: 2 }, name: "article_text_search" }) // Search using the text index db.articles.find({ $text: { $search: "mongodb aggregation" } }) // Sort by relevance score db.articles.find( { $text: { $search: "mongodb aggregation" } }, { score: { $meta: "textScore" } } ).sort({ score: { $meta: "textScore" } }) ``` ## Geospatial Index (2dsphere) Index for querying location data stored as GeoJSON. ```javascript db.places.createIndex({ location: "2dsphere" }) db.places.insertOne({ name: "MongoDB HQ", location: { type: "Point", coordinates: [-73.9857, 40.7484] // [longitude, latitude] } }) // Find places within 5 km of a point db.places.find({ location: { $near: { $geometry: { type: "Point", coordinates: [-73.9857, 40.7484] }, $maxDistance: 5000 // meters } } }) ``` ## Hashed Index Supports hash-based sharding. Provides even distribution for shard keys. ```javascript db.sessions.createIndex({ userId: "hashed" }) // Used for hash-based sharding sh.shardCollection("mydb.sessions", { userId: "hashed" }) ``` ## Wildcard Index Indexes all fields or fields matching a pattern. Useful for documents with unpredictable or dynamic field names. ```javascript // Index all fields in the document db.logs.createIndex({ "$**": 1 }) // Index all fields under a specific path db.products.createIndex({ "attributes.$**": 1 }) // Query any attribute without knowing field names in advance db.products.find({ "attributes.color": "red" }) db.products.find({ "attributes.weight": { $gte: 10 } }) ``` ## TTL Index (Time-To-Live) Automatically deletes documents after a specified time period. The field must contain a Date value. ```javascript // Documents expire 24 hours after createdAt db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 86400 }) // Documents expire 7 days after lastAccessed db.cache.createIndex({ lastAccessed: 1 }, { expireAfterSeconds: 604800 }) // Modify TTL on an existing index db.runCommand({ collMod: "sessions", index: { keyPattern: { createdAt: 1 }, expireAfterSeconds: 3600 } }) ``` ## Partial Index Indexes only documents matching a filter expression. Reduces index size and improves write performance. ```javascript // Only index active users db.users.createIndex( { email: 1 }, { partialFilterExpression: { isActive: true } } ) // Only index orders above $100 db.orders.createIndex( { customerId: 1, orderDate: -1 }, { partialFilterExpression: { total: { $gte: 100 } } } ) ``` ## Sparse Index Only includes documents that contain the indexed field. Documents missing the field are excluded from the index. ```javascript db.contacts.createIndex({ phone: 1 }, { sparse: true }) // Only documents that have a "phone" field are in the index // Useful when the field is optional and you want unique + sparse db.contacts.createIndex({ phone: 1 }, { unique: true, sparse: true }) ``` ## Atlas Search Index MongoDB Atlas provides Lucene-based full-text search via Atlas Search indexes. ```javascript // Create an Atlas Search index (via Atlas UI, CLI, or API) // Index definition: { "mappings": { "dynamic": false, "fields": { "title": { "type": "string", "analyzer": "lucene.standard" }, "description": { "type": "string", "analyzer": "lucene.english" }, "category": { "type": "stringFacet" } } } } // Query using $search in an aggregation pipeline db.products.aggregate([ { $search: { index: "product_search", compound: { must: [{ text: { query: "wireless headphones", path: "title" } }], filter: [{ text: { query: "electronics", path: "category" } }] } }}, { $limit: 10 }, { $project: { title: 1, price: 1, score: { $meta: "searchScore" } } } ]) ``` ## Vector Search Index Atlas Vector Search enables semantic search using vector embeddings. ```javascript // Vector search index definition (via Atlas UI or API) { "fields": [{ "type": "vector", "path": "embedding", "numDimensions": 1024, "similarity": "cosine" }] } // Query using $vectorSearch db.documents.aggregate([ { $vectorSearch: { index: "vector_index", path: "embedding", queryVector: [0.12, -0.34, 0.56, /* ... 1024 dimensions */], numCandidates: 100, limit: 10 }}, { $project: { title: 1, content: 1, score: { $meta: "vectorSearchScore" } } } ]) ``` ## Query Analysis with explain() Use `explain()` to understand how MongoDB executes a query and whether indexes are being used. ```javascript // Check if a query uses an index db.users.find({ email: "ada@example.com" }).explain("executionStats") // Key fields to check in the output: // - winningPlan.stage: "IXSCAN" means an index is used // - winningPlan.stage: "COLLSCAN" means a full collection scan (no index) // - executionStats.totalDocsExamined: documents scanned // - executionStats.nReturned: documents returned // Compare index candidates db.orders.find({ customerId: "abc", status: "shipped" }) .sort({ orderDate: -1 }) .explain("allPlansExecution") ``` ## Managing Indexes ```javascript // List all indexes on a collection db.users.getIndexes() // Drop a specific index by name db.users.dropIndex("email_1") // Drop all non-_id indexes db.users.dropIndexes() // Hide an index (stops the query planner from using it, without dropping) db.users.hideIndex("email_1") db.users.unhideIndex("email_1") ``` ## Tips - Follow the ESR rule for compound indexes: **E**quality, **S**ort, **R**ange. - Use `explain()` regularly to verify your queries hit the expected indexes. - Avoid over-indexing -- each index adds overhead to write operations. - Partial and sparse indexes save space when fields are optional. - In MongoDB Atlas, the Performance Advisor recommends indexes based on slow queries.