基于MongoDB Java Driver 3.6.3实现正则过滤+分组去重聚合查询
嘿,这个需求我熟!针对你用MongoDB Java Driver 3.6.3实现正则匹配+分组去重的场景,我整理了一套靠谱的方案,咱们一步步来:
核心实现思路
要达成你的目标,聚合管道需要三个关键阶段:
- $match:先筛选出
name以"John"开头的文档,用正则表达式精准匹配 - $group:按
name字段分组,确保每个name只出现一次,同时保留该分组下的一个category(比如第一个匹配到的,或者你需要的其他逻辑) - $project:把分组后的结果映射成你想要的输出结构
先在MongoDB Shell验证逻辑
先在Shell里跑一遍聚合命令,确认结果符合预期:
db.your_collection.aggregate([ // 筛选name以John开头的文档,"i"可选,代表不区分大小写 { $match: { name: { $regex: "^John", $options: "i" } } }, // 按name分组,取第一个category { $group: { _id: "$name", category: { $first: "$category" } } }, // 调整输出字段,隐藏默认的_id { $project: { _id: 0, name: "$_id", category: 1 } } ])
运行后得到的结果就是你要的:
[ { "name": "John Snow", "category": 1 }, { "name": "John Lennon", "category": 2 } ]
Java Driver 3.6.3 代码实现
接下来把上面的逻辑转成Java代码,完全适配3.6.3版本的驱动:
import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Aggregates; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; import com.mongodb.client.model.Accumulators; import org.bson.Document; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class JohnNameAggregation { public static void main(String[] args) { // 初始化MongoClient,根据你的实际连接配置调整 try (MongoClient mongoClient = new MongoClient("localhost", 27017)) { MongoDatabase db = mongoClient.getDatabase("your_db_name"); MongoCollection<Document> collection = db.getCollection("your_collection_name"); // 构建$match阶段:正则匹配name以John开头 Document matchStage = Aggregates.match(Filters.regex("name", "^John")); // 构建$group阶段:按name分组,取第一个category Document groupStage = Aggregates.group( "$name", Accumulators.first("category", "$category") ); // 构建$project阶段:调整输出字段 Document projectStage = Aggregates.project(Projections.fields( Projections.excludeId(), Projections.computed("name", "$_id"), Projections.include("category") )); // 执行聚合查询并获取结果 List<Document> results = collection.aggregate( Arrays.asList(matchStage, groupStage, projectStage) ).into(new ArrayList<>()); // 打印结果 results.forEach(doc -> System.out.println(doc.toJson())); } } }
几个关键点说明
- 正则匹配:如果需要不区分大小写,把
Filters.regex("name", "^John")改成Filters.regex("name", "^John", "i")就行 - 分组逻辑:
$group的_id设为$name是去重的核心,这样每个name只会生成一个分组;如果不想保留第一个category,换成Accumulators.min("category", "$category")(取最小category)或者Accumulators.max都可以,按需调整 - 驱动版本适配:3.6.3版本的驱动用
Aggregates、Filters这些工具类构建聚合阶段,和高版本API兼容,但别用3.6之后才出的新特性哦
内容的提问来源于stack exchange,提问作者Frido
相关产品推荐
相关产品推荐

