Indexing
Create indexes for fast O(log n) query performance
Overview
Indexes dramatically improve query performance by providing O(log n) lookups instead of O(n) full collection scans. jasonisnthappy uses B-tree indexes for efficient range queries and exact matches.
Without an index, queries must scan every document in the collection. With an index, the database can quickly locate matching documents.
Single Field Index
Create an index on a single field for fast lookups:
// Create index on email field
db.create_index("users", "email", true)?; // true = unique
// Non-unique index
db.create_index("users", "age", false)?;
# Create index on email field
db.create_index("users", "email_idx", "email", unique=True)
# Non-unique index
db.create_index("users", "age_idx", "age", unique=False)
// Create index on email field
db.createIndex('users', 'email_idx', 'email', true); // true = unique
// Non-unique index
db.createIndex('users', 'age_idx', 'age', false);
// Create index on email field
err := db.CreateIndex("users", "email_idx", "email", true) // true = unique
// Non-unique index
err = db.CreateIndex("users", "age_idx", "age", false)
Queries on indexed fields will automatically use the index:
// Fast lookup using index
let user = users.find_one("email is 'alice@example.com'")?;
# Fast lookup using index
user = coll.find_one("email = 'alice@example.com'")
// Fast lookup using index
const user = await users.findOne("email is 'alice@example.com'");
// Fast lookup using index
user, err := users.FindOne("email is 'alice@example.com'")
Compound Index
Create an index on multiple fields together for queries that filter on multiple fields:
// Index on city and age together
db.create_compound_index("users", &["city", "age"], false)?;
# Index on city and age together
db.create_compound_index("users", "city_age_idx", ["city", "age"], unique=False)
// Index on city and age together
db.createCompoundIndex('users', 'city_age_idx', ['city', 'age'], false);
// Index on city and age together
err := db.CreateCompoundIndex("users", "city_age_idx", []string{"city", "age"}, false)
This index speeds up queries that filter on both fields:
// This query will use the compound index
let results = users.find("city is 'NYC' and age > 25")?;
# This query will use the compound index
results = coll.find("city = 'NYC' and age > 25")
// This query will use the compound index
const results = await users.find("city is 'NYC' and age > 25");
// This query will use the compound index
results, err := users.Find("city is 'NYC' and age > 25")
Text Index
Create a full-text search index on one or more fields. See the Text Search guide for detailed usage:
// Create text index on multiple fields
db.create_text_index("posts", "search_idx", &["title", "content", "tags"])?;
# Create text index on single field
db.create_text_index("posts", "search_idx", "content")
// Create text index on multiple fields
db.createTextIndex('posts', 'search_idx', ['title', 'content', 'tags']);
// Create text index on multiple fields
err := db.CreateTextIndex("posts", "search_idx", []string{"title", "content", "tags"})
Use the text index for full-text search:
let results = posts.search("rust database")?;
for result in results {
println!("Score: {:.2}, Title: {}",
result.score, result.doc_id);
}
results = coll.search("rust database")
for result in results:
print(f"Score: {result['score']:.2f}")
const results = await posts.search('rust database');
results.forEach(result => {
console.log(`Score: ${result.score.toFixed(2)}`);
});
results, err := posts.Search("rust database")
for _, result := range results {
fmt.Printf("Score: %.2f\n", result.Score)
}
Unique Constraints
Unique indexes prevent duplicate values for a field:
// Create unique index on email
db.create_index("users", "email", true)?;
// Attempting to insert duplicate email will fail
let result = users.insert(json!({
"email": "alice@example.com" // Error if already exists
}));
match result {
Err(Error::UniqueConstraintViolation) => {
println!("Email already exists");
}
_ => {}
}
# Create unique index on email
db.create_index("users", "email_idx", "email", unique=True)
# Attempting to insert duplicate email will fail
try:
coll.insert({"email": "alice@example.com"})
except RuntimeError as e:
if "unique" in str(e).lower():
print("Email already exists")
// Create unique index on email
db.createIndex('users', 'email_idx', 'email', true);
// Attempting to insert duplicate email will fail
try {
await users.insert({ email: 'alice@example.com' });
} catch (err) {
if (err.message.includes('unique')) {
console.log('Email already exists');
}
}
// Create unique index on email
err := db.CreateIndex("users", "email_idx", "email", true)
// Attempting to insert duplicate email will fail
_, err = users.Insert(map[string]interface{}{
"email": "alice@example.com",
})
if err != nil && strings.Contains(err.Error(), "unique") {
fmt.Println("Email already exists")
}
List Indexes
List all indexes on a collection:
let indexes = db.list_indexes("users")?;
for index in indexes {
println!("{}: {:?} (unique: {})",
index.name,
index.fields,
index.unique
);
}
indexes = db.list_indexes("users")
for idx in indexes:
print(f"{idx['name']}: {idx['fields']} (unique: {idx['unique']})")
const indexes = db.listIndexes('users');
indexes.forEach(idx => {
console.log(`${idx.name}: ${idx.fields} (unique: ${idx.unique})`);
});
indexes, err := db.ListIndexes("users")
for _, idx := range indexes {
fmt.Printf("%s: %v (unique: %v)\n",
idx.Name,
idx.Fields,
idx.Unique
)
}
Drop Index
Remove an index from a collection:
db.drop_index("users", "email_idx")?;
db.drop_index("users", "email_idx")
db.dropIndex('users', 'email_idx');
err := db.DropIndex("users", "email_idx")
Performance Considerations
- Index Everything You Query: If you frequently query by a field, create an index on it
- Write Performance: Indexes slightly slow down inserts and updates as the index must be maintained
- Memory Usage: Indexes consume additional memory and disk space
- Compound Index Order: Put the most selective field first for best performance
- Unique Indexes: Enforce data integrity while providing fast lookups