Groovy获取MongoDB聚合结果时出现ClassCastException问题求助
解决Groovy中MongoDB v4.x驱动AggregateIterable的GString转String类型转换异常
问题原因
MongoDB Java Sync Driver v4.x对参数类型校验更严格,Groovy的GStringImpl(双引号插值生成的字符串)与Java原生String并非同一类型。旧版驱动可能隐式处理了GString到String的转换,但新版驱动未做此兼容,导致聚合管道中传入的GString在后续结果处理时触发ClassCastException。
解决方案
核心是确保聚合管道中所有字符串参数均为Java原生String类型,可通过以下方式实现:
1. 使用Groovy单引号字符串
Groovy中单引号包裹的字符串是原生Java String,双引号则生成GString。如果不需要字符串插值,直接用单引号定义聚合阶段的操作符、字段名等:
// 正确:单引号生成Java String def matchStage = Aggregates.match(Filters.eq('username', 'john_doe')) def groupStage = Aggregates.group('$department', Accumulators.sum('total', 1)) def pipeline = Arrays.asList(matchStage, groupStage)
2. 显式转换GString为String
如果需要动态插值(必须用双引号),通过toString()或as String强制转换为Java String:
def userName = 'john_doe' def departmentField = 'department' // 方式1:调用toString()转换 def matchValue = "${userName}".toString() def matchStage = Aggregates.match(Filters.eq('username', matchValue)) // 方式2:使用as关键字转换 def groupId = ("$${departmentField}") as String def groupStage = Aggregates.group(groupId, Accumulators.sum('total', 1)) def pipeline = Arrays.asList(matchStage, groupStage) def results = collection.aggregate(pipeline) def resultList = results.toList() // 正常执行
3. 检查Document构建的聚合阶段
如果直接用Document手动构建聚合阶段,确保键和值中的字符串都是Java String:
def fieldName = 'age' // 错误:GString作为Document的键 // def groupStage = new Document('$group', new Document("$$${fieldName}", 1)) // 正确:显式转换键为String def groupKey = ("$$${fieldName}").toString() def groupStage = new Document('$group', new Document(groupKey, 1))
验证方法
修改完成后,尝试调用results.toList()、results.iterator()等方法,若不再触发ClassCastException,则问题解决。
内容的提问来源于stack exchange,提问作者ionised
相关产品推荐
相关产品推荐

