
往期精选
Java 江湖的兄弟姐妹们!今天咱要探索 MongoDB 里的 "数据导航系统"------ 索引操作!想象一下,没有索引的数据集合就像堆满杂物的仓库,找个东西得翻箱倒柜;而有了索引,就好比给仓库装了智能导航,分分钟定位到目标数据。接下来,咱就从基础操作到高阶玩法,手把手教你成为索引操作的 "老司机"!
一、索引入门:给数据装上导航
在 MongoDB 的世界里,索引就像给数据贴上了 "GPS 定位标签",能大幅提升查询速度。不过,就像不是所有路都要装导航一样,也不是所有字段都需要建索引。咱们先从基础操作学起!
1. 创建单字段索引:给单个属性加导航
假设我们有个 users 集合,存储用户信息,每个文档结构如下:
perl
{
"userId": "u123",
"username": "jack",
"age": 25,
"email": "[email protected]"
}
如果我们经常根据 username 字段查询用户,就可以给它建个索引。在 Java 代码里这么操作:
java
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Indexes.ascending;
public class SingleFieldIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.createIndex({username: 1})
// 创建升序索引,1表示升序,-1表示降序,这里给username字段建升序索引
collection.createIndex(ascending("username"));
System.out.println("单字段索引创建成功!");
}
}
这就好比给每个用户的名字都挂上了显眼的 "门牌",下次按名字找人就快多啦!
2. 查看索引:瞧瞧都装了哪些导航
创建完索引后,咱们可以查看一下当前集合都有哪些索引:
ini
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class ListIndexesExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.getIndexes()
// 获取集合的所有索引信息
collection.listIndexes().forEach(index -> System.out.println(index));
}
}
运行代码后,你会看到类似下面的输出,能清楚看到每个索引的字段和排序方式:
json
{
"_id_": {
"v": 2,
"key": {
"_id": 1
},
"name": "_id_",
"ns": "testdb.users"
},
"username_1": {
"v": 2,
"key": {
"username": 1
},
"name": "username_1",
"ns": "testdb.users"
}
}
3. 删除索引:拆掉不需要的导航
如果某个索引不再需要了,比如我们给 username 建的索引打算换掉,就可以删除它:
java
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class DropIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.dropIndex({username: 1})
// 删除指定的索引,这里删除username字段的索引
collection.dropIndex(new Document("username", 1));
System.out.println("指定索引删除成功!");
}
}
或者,如果你想清空所有自定义索引(保留 _id 索引):
ini
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class DropAllIndexesExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.dropIndexes()
// 删除集合的所有自定义索引
collection.dropIndexes();
System.out.println("所有自定义索引删除成功!");
}
}
二、进阶索引:打造个性化导航
1. 复合索引:多个属性的联合导航
有时候,我们需要根据多个字段组合查询,这时候就可以创建复合索引。比如,经常根据 age 和 email 一起查询用户:
java
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Indexes.ascending;
public class CompoundIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.createIndex({age: 1, email: 1})
// 创建复合索引,按照age和email字段升序排列
collection.createIndex(ascending("age", "email"));
System.out.println("复合索引创建成功!");
}
}
复合索引就像给数据加上了 "组合导航",按组合条件查询时速度飞快!但要注意,复合索引的字段顺序很重要,查询条件要匹配索引字段顺序才能生效。
2. 唯一索引:禁止重复的特殊导航
如果某个字段的值不能重复,比如 userId ,就可以创建唯一索引:
ini
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Indexes.ascending;
import com.mongodb.client.model.IndexOptions;
public class UniqueIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
IndexOptions options = new IndexOptions().unique(true);
// 对应MongoDB查询语句:db.users.createIndex({userId: 1}, {unique: true})
// 创建唯一索引,确保userId字段的值唯一
collection.createIndex(ascending("userId"), options);
System.out.println("唯一索引创建成功!");
}
}
要是往集合里插入 userId 重复的文档,MongoDB 会直接报错,就像导航系统发现重复路线,直接喊 "此路不通"!
3. 部分索引:按需定制的导航
当我们只想对集合中的部分文档创建索引时,就可以用部分索引。比如,只对 age 大于 20 的用户创建索引:
java
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Indexes.ascending;
import com.mongodb.client.model.IndexOptions;
import static com.mongodb.client.model.Filters.gt;
public class PartialIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
IndexOptions options = new IndexOptions()
.partialFilterExpression(gt("age", 20));
// 对应MongoDB查询语句:db.users.createIndex({age: 1}, {partialFilterExpression: {age: {$gt: 20}}})
// 创建部分索引,仅对age大于20的文档生效
collection.createIndex(ascending("age"), options);
System.out.println("部分索引创建成功!");
}
}
这相当于给特定条件的数据 "单独开通快速通道",既节省资源,又能提升查询效率。
三、高阶索引:解锁超能力导航
1. 文本索引:全文搜索的导航神器
如果我们需要在 MongoDB 中进行全文搜索,比如搜索用户的 username ,就可以创建文本索引:
arduino
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Indexes.text;
public class TextIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.createIndex({username: "text"})
// 创建文本索引,支持对username字段进行全文搜索
collection.createIndex(text("username"));
System.out.println("文本索引创建成功!");
}
}
创建完文本索引后,就可以用 $text 操作符进行搜索啦:
ini
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Filters.text;
public class TextSearchExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("users");
// 对应MongoDB查询语句:db.users.aggregate([{ $match: { $text: { $search: "jack" } } }])
// 搜索username包含jack的用户
AggregateIterable<Document> result = collection.aggregate(List.of(
match(text("jack"))
));
for (Document document : result) {
System.out.println(document);
}
}
}
这就像给数据加上了 "智能搜索引擎",搜索关键词秒出结果!
2. 地理空间索引:定位数据的专属导航
在处理地理位置数据时,地理空间索引就派上用场了。假设我们有个 shops 集合,存储店铺的经纬度信息:
json
{
"shopId": "s1",
"name": "便利店",
"location": {
"type": "Point",
"coordinates": [116.4074, 39.9042] // 经度,纬度
}
}
我们可以给 location 字段创建地理空间索引:
java
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Indexes.geo2dsphere;
public class GeoSpatialIndexExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("shops");
// 对应MongoDB查询语句:db.shops.createIndex({location: "2dsphere"})
// 创建地理空间索引,适用于球面几何数据
collection.createIndex(geo2dsphere("location"));
System.out.println("地理空间索引创建成功!");
}
}
有了地理空间索引,就可以进行附近店铺查询等操作:
typescript
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Filters.near;
import static com.mongodb.client.model.Filters.nearSphere;
public class GeoSpatialSearchExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("shops");
// 对应MongoDB查询语句:db.shops.aggregate([{ $match: { location: { $nearSphere: { $geometry: { type: "Point", coordinates: [116.4074, 39.9042] }, $maxDistance: 1000 } } } }])
// 查询距离指定坐标1000米内的店铺
AggregateIterable<Document> result = collection.aggregate(List.of(
match(nearSphere("location", new Document("type", "Point").append("coordinates", Arrays.asList(116.4074, 39.9042)), 1000))
));
for (Document document : result) {
System.out.println(document);
}
}
}
这简直就是给地理位置数据装上了 "卫星导航",附近的店铺位置一查便知!
四、索引使用避坑指南:别让导航带偏
- 索引不是越多越好:索引虽然能加快查询速度,但也会增加写入和存储成本。就像城市里导航太多反而容易迷路,建索引要按需来,别一股脑全上!
- 注意查询条件与索引匹配:复合索引的字段顺序很关键,查询条件要和索引字段顺序一致才能生效。不然就像导航路线和实际路线不匹配,白费力气!
- 唯一索引的坑:插入数据时要确保唯一索引字段的值不重复,不然分分钟报错,就像重复的路线导航可不认!
- 索引更新成本:数据更新时,索引也会跟着更新。频繁更新数据的字段,建索引要慎重,不然更新操作会变得巨慢!
五、总结:成为索引操作大师
通过上面的学习,相信你已经对 MongoDB 的索引操作有了全面的了解!从基础的单字段索引,到进阶的复合索引、唯一索引,再到高阶的文本索引、地理空间索引,每一种索引都有它独特的用途。
但记住,纸上得来终觉浅,绝知此事要躬行!赶紧去自己的项目里实践这些索引操作,多尝试不同的组合。要是在使用过程中遇到问题,欢迎在评论区留言,咱们一起把索引这门 "导航技术" 玩得明明白白!觉得文章有用的,点赞、收藏、转发走一波,让更多小伙伴加入索引操作 "老司机" 的队伍!下次咱们再探索 MongoDB 的其他 "隐藏技能",不见不散!