Kotlin环境下MongoDB Criteria的$in操作符异常问题确认
Spring Data MongoDB $in查询嵌套数组问题解决
问题现象
使用Spring Data MongoDB的Criteria构建or组合查询时,调用in()方法传入List参数,生成的MongoDB查询语句中$in条件出现嵌套数组([["toto"]]),导致查询无结果:
val names = mutableListOf("toto") Criteria().orOperator( mutableListOf( Criteria("fieldA.name").`in`(names), Criteria("fieldB.name").`in`(names) ) )
日志显示的错误查询语句:
Executing count: { "$or" : [{ "fieldA.urn" : { "$in" : [["toto"]]}}, { "fieldB.urn" : { "$in" : [["toto"]]}}]} in collection: fields
但改用is()方法传入单个元素时,查询正常返回结果:
Criteria().orOperator( mutableListOf( Criteria("fieldA.name").`is`(names[0]), Criteria("fieldB.name").`is`(names[0]) ) )
该问题存在于以下版本:
- org.springframework.boot:spring-boot-starter-data-mongodb:2.7.9
- org.springframework.data:spring-data-mongodb:3.4.8
- org.mongodb:mongodb-driver-core:4.10.2
原因
这是Spring Data MongoDB的框架bug:当in()方法接收List类型参数,且处于orOperator等组合查询场景时,框架会错误地将外层List再次包装为数组,生成不符合MongoDB规范的嵌套数组条件。MongoDB的$in仅接受单层数组作为匹配值,因此嵌套数组无法匹配任何数据。
解决方法
方法1:将List转为可变参数传入
利用Kotlin的*运算符把List展开为可变参数,避免框架重复包装:
val names = mutableListOf("toto") Criteria().orOperator( mutableListOf( Criteria("fieldA.name").`in`(*names.toTypedArray()), Criteria("fieldB.name").`in`(*names.toTypedArray()) ) )
方法2:使用inValues()替代in()
inValues()方法专门针对集合类型参数设计,不会产生嵌套数组问题:
val names = mutableListOf("toto") Criteria().orOperator( mutableListOf( Criteria("fieldA.name").inValues(names), Criteria("fieldB.name").inValues(names) ) )
方法3:升级框架版本
该bug已在Spring Data MongoDB 3.4.9及以上版本修复,对应Spring Boot版本为2.7.10及以上,升级后即可直接使用原写法正常生成查询语句。
内容的提问来源于stack exchange,提问作者Val
相关产品推荐
相关产品推荐

