我会从基础到进阶,结合代码实例,为你全面解析。

准备工作:环境搭建
你需要在你的 Java 项目中添加 MongoDB Java 驱动的依赖。
使用 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' // 请使用最新版本
连接到 MongoDB
在进行任何查询之前,你需要先建立一个到 MongoDB 服务器的连接。
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
public class MongoQueryExample {
public static void main(String[] args) {
// 1. 定义连接字符串
// 格式: mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
String uri = "mongodb://localhost:27017";
// 2. 创建 MongoClient 实例
// 从 MongoDB 3.12+ 和 Java 驱动 4.0+ 开始,推荐使用 MongoClient 而不是 Mongo
try (MongoClient mongoClient = MongoClients.create(uri)) {
// 3. 获取数据库
// 如果数据库不存在,MongoDB 会在第一次插入数据时自动创建
MongoDatabase database = mongoClient.getDatabase("mydb");
// 4. 获取集合
// 如果集合不存在,MongoDB 会在第一次插入数据时自动创建
MongoCollection<Document> collection = database.getCollection("users");
System.out.println("成功连接到 MongoDB 并获取集合 'users'");
// ... 在这里进行查询操作 ...
}
}
}
查询操作详解
查询的核心是构建一个 Filters (查询条件) 对象,然后将其传递给 find() 方法。
1 基础查询 (find())
find() 方法返回一个 FindIterable<Document>,你需要遍历它来获取结果。

// 查询集合中的所有文档
FindIterable<Document> allDocuments = collection.find();
for (Document doc : allDocuments) {
System.out.println(doc.toJson());
}
2 等值查询 (eq)
使用 Filters.eq() 来查找字段值等于特定值的文档。
// 查找 name 为 "Alice" 的用户
Document queryFilter = new Document("name", "Alice"); // 这是最简单的方式
// 或者使用 Filters
// Bson queryFilter = Filters.eq("name", "Alice");
FindIterable<Document> results = collection.find(queryFilter);
for (Document doc : results) {
System.out.println(doc.toJson());
}
3 比较查询
MongoDB 提供了丰富的比较操作符,通过 Filters 类使用。
| 操作符 | Java 方法 | 示例 (查找年龄大于 30 的用户) |
|---|---|---|
$gt (大于) |
gt() |
Filters.gt("age", 30) |
$gte (大于等于) |
gte() |
Filters.gte("age", 30) |
$lt (小于) |
lt() |
Filters.lt("age", 30) |
$lte (小于等于) |
lte() |
Filters.lte("age", 30) |
$ne (不等于) |
ne() |
Filters.ne("age", 30) |
$in (在...之中) |
in() |
Filters.in("name", "Alice", "Bob", "Charlie") |
// 查找年龄大于 30 的用户
Bson ageFilter = Filters.gt("age", 30);
collection.find(ageFilter).forEach(doc -> System.out.println(doc.toJson()));
// 查找年龄在 25 到 35 之间的用户 (AND 条件)
Bson ageRangeFilter = Filters.and(
Filters.gte("age", 25),
Filters.lte("age", 35)
);
collection.find(ageRangeFilter).forEach(doc -> System.out.println(doc.toJson()));
4 逻辑查询 (and, or, not)
使用 Filters.and(), Filters.or(), Filters.not() 来组合多个查询条件。
// 查找年龄大于 30 *** 城市为 "New York" 的用户
Bson andFilter = Filters.and(
Filters.gt("age", 30),
Filters.eq("city", "New York")
);
collection.find(andFilter).forEach(doc -> System.out.println(doc.toJson()));
// 查找城市为 "New York" **或者** 城市为 "London" 的用户
Bson orFilter = Filters.or(
Filters.eq("city", "New York"),
Filters.eq("city", "London")
);
collection.find(orFilter).forEach(doc -> System.out.println(doc.toJson()));
5 字段查询 (exists, type, mod)
| 操作符 | Java 方法 | 说明 |
|---|---|---|
$exists |
exists() |
检查字段是否存在 |
$type |
type() |
检查字段类型 |
$mod |
mod() |
取模运算 |
// 查找有 "phone" 字段的所有用户
Bson existsFilter = Filters.exists("phone");
collection.find(existsFilter).forEach(doc -> System.out.println(doc.toJson()));
// 查找 "age" 字段类型为 Number (BsonType.NUMBER) 的用户
Bson typeFilter = Filters.type("age", BsonType.NUMBER);
collection.find(typeFilter).forEach(doc -> System.out.println(doc.toJson()));
// 查找 age % 10 == 0 (即年龄是10的倍数) 的用户
Bson modFilter = Filters.mod("age", 10, 0);
collection.find(modFilter).forEach(doc -> System.out.println(doc.toJson()));
6 字符串查询 (regex, options)
使用 Filters.regex() 进行正则表达式匹配。

// 查找名字以 "A" 开头的用户 (不区分大小写)
Bson regexFilter = Filters.regex("name", "^A", "i");
collection.find(regexFilter).forEach(doc -> System.out.println(doc.toJson()));
// 查找名字中包含 "li" 的用户
Bson containsFilter = Filters.regex("name", "li");
collection.find(containsFilter).forEach(doc -> System.out.println(doc.toJson()));
7 查询嵌套文档和数组
对于嵌套文档,使用 来访问字段,对于数组,默认情况下,只要文档中数组包含该元素即可。
// 假设有如下文档:
// { "name": "John", "address": { "street": "123 Main St", "city": "Boston" } }
// 查找住在 Boston 的用户
Bson nestedFilter = new Document("address.city", "Boston");
// 或者使用 Filters.eq("address.city", "Boston")
collection.find(nestedFilter).forEach(doc -> System.out.println(doc.toJson()));
// 假设有如下文档:
// { "name": "David", "hobbies": ["reading", "hiking", "coding"] }
// 查找有 "hiking" 爱好的用户
Bson arrayFilter = Filters.eq("hobbies", "hiking");
collection.find(arrayFilter).forEach(doc -> System.out.println(doc.toJson()));
8 查询数组元素 (elemMatch)
如果你想对数组中的元素进行更复杂的条件匹配,需要使用 $elemMatch。
// 假设有如下文档:
// {
// "name": "Eve",
// "scores": [ { "subject": "math", "score": 95 }, { "subject": "english", "score": 88 } ]
// }
// 查找 scores 数组中至少有一个元素的 subject 是 "math" score 大于 90 的用户
Bson elemMatchFilter = Filters.elemMatch("scores",
Filters.and(
Filters.eq("subject", "math"),
Filters.gt("score", 90)
)
);
collection.find(elemMatchFilter).forEach(doc -> System.out.println(doc.toJson()));
查询结果处理
1 投影 (projection)
只返回你需要的字段,而不是整个文档。
// 只返回 name 和 age 字段,_id 默认返回
// 1 表示包含,0 表示排除
Document projection = new Document("name", 1).append("age", 1);
// 查询所有用户,但只显示 name 和 age
collection.find().projection(projection).forEach(doc -> System.out.println(doc.toJson()));
// 排除 _id 字段
Document projectionWithoutId = new Document("name", 1).append("age", 1).append("_id", 0);
collection.find().projection(projectionWithoutId).forEach(doc -> System.out.println(doc.toJson()));
2 排序 (sort)
使用 Sorts 类来指定排序规则。
// 按 age 字段升序排列
collection.find().sort(Sorts.ascending("age")).forEach(doc -> System.out.println(doc.toJson()));
// 按 age 字段降序排列
collection.find().sort(Sorts.descending("age")).forEach(doc -> System.out.println(doc.toJson()));
// 先按 city 升序,再按 age 降序
collection.find().sort(Sorts.orderBy(Sorts.ascending("city"), Sorts.descending("age")))
.forEach(doc -> System.out.println(doc.toJson()));
3 分页 (skip 和 limit)
skip(n): 跳过前n个结果。limit(m): 只返回最多m个结果。
// 获取第 2 页数据,每页 10 条数据 (跳过 10 条,取 10 条) collection.find().skip(10).limit(10).forEach(doc -> System.out.println(doc.toJson()));
使用 POJO (Plain Old Java Object) 进行映射
直接操作 Document 不是很方便,你可以将 MongoDB 的文档映射到 Java 对象。
-
创建一个 POJO 类
import org.bson.types.ObjectId; public class User { private ObjectId id; private String name; private int age; private String city; // Getters and Setters public ObjectId getId() { return id; } public void setId(ObjectId id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", city='" + city + '\'' + '}'; } } -
修改查询代码
// 需要添加一个解码器注册表 CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries( MongoClient.getDefaultCodecRegistry(), CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build()) ); // 在获取集合时应用 MongoCollection<User> userCollection = database.getCollection("users", User.class) .withCodecRegistry(pojoCodecRegistry); // 现在可以直接查询并返回 User 对象列表 List<User> users = userCollection.find(Filters.gt("age", 30)) .sort(Sorts.ascending("name")) .into(new ArrayList<>()); for (User user : users) { System.out.println(user); }使用 POJO 可以让代码类型更安全,更易于维护。
| 操作 | Java 驱动方法/类 | 说明 |
|---|---|---|
| 连接 | MongoClients.create(uri) |
创建客户端 |
| 获取集合 | database.getCollection("name") |
获取操作的集合 |
| 查询条件 | Filters.eq(), Filters.gt(), Filters.or() 等 |
构建查询 Bson 对象 |
| 执行查询 | collection.find(filter) |
返回可迭代的 FindIterable |
| 投影 | .projection(new Document("field", 1)) |
指定返回的字段 |
| 排序 | .sort(Sorts.ascending("field")) |
对结果排序 |
| 分页 | .skip(N).limit(M) |
跳过 N 条,取 M 条 |
| POJO映射 | database.getCollection("name", MyClass.class) |
直接映射到Java对象 |
这份指南涵盖了 MongoDB Java 查询的大部分常用场景,你可以根据需要组合使用这些方法来实现复杂的查询逻辑。
