悠悠楠杉
Java操作MongoDB复杂查询实战指南
一、环境准备与基础配置
在开始复杂查询前,确保项目已引入最新Java驱动:
xml
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.9.1</version>
</dependency>
建立连接时建议配置连接池:
java
MongoClient client = MongoClients.create(
MongoClientSettings.builder()
.applyToConnectionPoolSettings(builder ->
builder.maxSize(20).minSize(5))
.applyConnectionString(new ConnectionString("mongodb://localhost"))
.build()
);
二、条件查询进阶技巧
1. 多条件组合查询
使用Filters
构建复合查询条件:java
Bson filter = and(
gt("price", 100),
or(
eq("category", "电子产品"),
regex("name", ".手机.")
),
exists("stock", true)
);
FindIterable
.sort(Sorts.descending("create_time"));
注意:MongoDB的$and
操作符会短路执行,将高选择性条件放在前面可提升性能。
2. 数组元素查询
处理数组字段时的特殊语法:
java
// 查询tags包含"促销"且长度大于3的文档
Bson arrayQuery = and(
all("tags", Arrays.asList("促销")),
expr(new Document("$gt", Arrays.asList("$size", 3)))
);
三、聚合查询实战
1. 基础聚合管道
典型的分组统计示例:java
List
match(gt("price", 50)),
group("$category",
sum("total", "$price"),
avg("avg_price", "$price")),
sort(descending("total"))
);
AggregateIterable
2. 多阶段聚合
复杂数据处理流程:
java
List<Bson> pipeline = Arrays.asList(
match(expr(new Document("$gt", Arrays.asList("$sales", "$stock")))), // 销售大于库存
lookup("shops", "shop_id", "_id", "shop_info"), // 关联查询
unwind("$shop_info"),
project(fields(
include("name", "price"),
computed("profit", new Document("$subtract",
Arrays.asList("$price", "$cost")))
))
);
四、性能优化要点
索引策略:
- 为高频查询字段创建复合索引
java collection.createIndex(Indexes.compoundIndex( Indexes.descending("create_time"), Indexes.text("product_name") ));
- 使用
explain()
分析查询计划
- 为高频查询字段创建复合索引
批量操作:
- 大批量查询时使用
batchSize()
- 写入时采用bulk操作
- 大批量查询时使用
游标控制:
java FindIterable<Document> iterable = collection.find() .noCursorTimeout(true) .maxTime(10, TimeUnit.SECONDS);
五、特殊查询场景处理
分页查询优化:
java Bson skipStage = skip((pageNum - 1) * pageSize); Bson limitStage = limit(pageSize); Bson sortStage = sort(Sorts.descending("_id")); // 建议使用唯一字段排序
地理空间查询:
java Bson geoQuery = nearSphere("location", new Point(new Position(116.404, 39.915)), 5000); // 5公里范围内
事务支持:
java try (ClientSession session = client.startSession()) { session.withTransaction(() -> { collection.updateOne(session, ...); otherCollection.deleteMany(session, ...); return null; }); }
六、错误处理建议
- 始终检查
MongoExecutionTimeoutException
- 处理DuplicateKeyException时考虑upsert操作
- 网络异常时实现重试机制