确保你的项目已配置 MongoDB Java 驱动
你需要确保你的 Java 项目已经包含了 MongoDB 的 Java 驱动(mongodb-driver-sync)。

如果你使用 Maven,在 pom.xml 中添加以下依赖:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.11.1</version> <!-- 建议使用最新版本 -->
</dependency>
如果你使用 Gradle,在 build.gradle 中添加:
implementation 'org.mongodb:mongodb-driver-sync:4.11.1' // 建议使用最新版本
基本索引创建
创建索引最直接的方法是使用 MongoCollection 对象的 createIndex() 方法。
示例代码
假设我们有一个 users 集合,我们想为 username 字段创建一个升序索引。

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class CreateIndexExample {
public static void main(String[] args) {
// 1. 创建 MongoDB 客户端连接
// 替换为你的 MongoDB 连接字符串
String uri = "mongodb://localhost:27017";
try (MongoClient mongoClient = MongoClients.create(uri)) {
// 2. 获取数据库和集合
MongoDatabase database = mongoClient.getDatabase("myDatabase");
MongoCollection<Document> collection = database.getCollection("users");
// 3. 定义要创建索引的文档
// "username" 是字段名, 1 表示升序 (ASCENDING)
// -1 表示降序 (DESCENDING)
Document index = new Document("username", 1);
// 4. 创建索引
// createIndex() 方法会返回创建的索引名称
String indexName = collection.createIndex(index);
System.out.println("索引创建成功! 索引名称: " + indexName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
代码解释:
MongoClients.create(uri): 创建一个与 MongoDB 服务器连接的客户端。database.getCollection("users"): 获取指定名称的集合对象。new Document("username", 1): 创建一个Document对象来定义索引,键是字段名,值是排序方向。1: 升序 (Ascending)-1: 降序 (Descending)
collection.createIndex(index): 执行创建索引的操作,MongoDB 会自动检查索引是否已存在,如果存在则不会重复创建。
创建复合索引
复合索引是基于多个字段的索引,这对于多条件查询(如 find({status: "A", age: 30}))的性能提升至关重要。
示例代码
为 status 字段创建升序索引,同时为 age 字段创建降序索引。
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class CreateCompoundIndexExample {
public static void main(String[] args) {
String uri = "mongodb://localhost:27017";
try (MongoClient mongoClient = MongoClients.create(uri)) {
MongoDatabase database = mongoClient.getDatabase("myDatabase");
MongoCollection<Document> collection = database.getCollection("users");
// 创建一个包含多个字段的文档来定义复合索引
// 索引的顺序非常重要!
Document compoundIndex = new Document()
.append("status", 1) // status 字段升序
.append("age", -1); // age 字段降序
String indexName = collection.createIndex(compoundIndex);
System.out.println("复合索引创建成功! 索引名称: " + indexName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键点:

- 顺序很重要:
status和age的顺序决定了索引的结构,上面的索引可以高效支持{"status": 1, "age": -1}的查询,但对于{"age": -1, "status": 1}的查询效率可能较低。 - 查询模式匹配:复合索引的“最左前缀原则”适用,即一个复合索引
(A, B, C)可以支持:AA, BA, B, C- 但不支持单独的
B或C的查询。
带有选项的索引创建
createIndex() 方法还接受一个 IndexOptions 对象,让你可以配置索引的各种高级属性。
常用选项
- 唯一索引 (
unique(true)): 确保集合中所有文档的索引字段值都是唯一的。 - 稀疏索引 (
sparse(true)): 只为包含索引字段的文档创建索引条目,可以节省空间并避免对null值的索引。 - TTL 索引 (
expireAfter(long, TimeUnit)): 用于自动在一定时间后删除文档,非常适合缓存或会话数据。 - 索引名称 (
name(String)): 为索引指定一个自定义名称。
示例代码:创建唯一索引和带名称的索引
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.Indexes;
import org.bson.Document;
public class CreateIndexWithOptionsExample {
public static void main(String[] args) {
String uri = "mongodb://localhost:27017";
try (MongoClient mongoClient = MongoClients.create(uri)) {
MongoDatabase database = mongoClient.getDatabase("myDatabase");
MongoCollection<Document> collection = database.getCollection("users");
// 方式一:使用传统的 Document 定义索引
Document indexDoc = new Document("email", 1);
// 创建 IndexOptions 对象
IndexOptions options = new IndexOptions()
.unique(true) // 设置为唯一索引
.name("unique_email_idx"); // 设置索引名称
String indexName1 = collection.createIndex(indexDoc, options);
System.out.println("带选项的索引创建成功! 索引名称: " + indexName1);
// 方式二:使用 Indexes 工具类 (更推荐,代码更清晰)
// 为 "lastLoginAt" 字段创建一个 TTL 索引,3600秒后过期
IndexOptions ttlOptions = new IndexOptions()
.expireAfter(3600L, java.util.concurrent.TimeUnit.SECONDS); // 1小时后过期
String indexName2 = collection.createIndex(Indexes.descending("lastLoginAt"), ttlOptions);
System.out.println("TTL 索引创建成功! 索引名称: " + indexName2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
管理现有索引
除了创建,你可能还需要查看、删除索引。
1 查看集合的所有索引
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
// ... 其他导入
// 在你的 main 方法中或单独的方法里
MongoDatabase database = mongoClient.getDatabase("myDatabase");
MongoCollection<Document> collection = database.getCollection("users");
System.out.println("--- 集合 'users' 的所有索引 ---");
try (MongoCursor<Document> cursor = collection.listIndexes().iterator()) {
while (cursor.hasNext()) {
Document indexDoc = cursor.next();
System.out.println(indexDoc.toJson());
}
}
输出示例:
--- 集合 'users' 的所有索引 ---
{
"v": 2,
"key": {
"_id": 1
},
"name": "_id_"
}
{
"v": 2,
"unique": true,
"key": {
"email": 1
},
"name": "unique_email_idx"
}
2 删除索引
你可以通过索引名称来删除索引。
// 删除名为 "unique_email_idx" 的索引
collection.dropIndex("unique_email_idx");
// 或者删除一个由字段定义的索引 (如果它是默认名称)
// collection.dropIndex(new Document("username", 1));
System.out.println("索引 'unique_email_idx' 已删除。");
最佳实践与注意事项
- 在开发环境测试:在生产环境创建索引可能会锁定集合并影响性能,建议在开发或预发布环境中充分测试。
- 在低峰期创建:大型索引的创建可能会消耗大量 I/O 和 CPU 资源,导致数据库响应变慢,请在业务低峰期执行。
- 使用后台创建:对于非常大的集合,可以使用
createIndex()的background选项在后台创建索引,这样不会阻塞其他数据库操作。IndexOptions options = new IndexOptions().background(true); collection.createIndex(new Document("large_field", 1), options); - 不要过度索引:每个索引都会占用磁盘空间,并且会降低
insert、update和delete的速度(因为需要更新索引),只为你的查询模式创建必要的索引。 - 分析查询性能:使用
explain()方法来分析你的查询是否有效地使用了索引。// 查看查询的执行计划 collection.find(new Document("status", "A")) .explain(); // 或者 .explain("executionStats") 获取更详细的统计信息 - 使用
Indexes工具类:如示例所示,com.mongodb.client.model.Indexes提供了丰富的静态方法(如ascending(),descending(),text(),compoundIndex()等),使构建索引定义的代码更具可读性。
希望这份详细的指南能帮助你在 Java 中熟练地操作 MongoDB 索引!
