Scala Slick 3.3.x如何将两个filterOpt合并为OR条件查询?
问题:合并Slick的filterOpt实现OR逻辑查询条件
我在Scala中定义了两个可选字符串序列:
val firstSeq = Some(Seq("1", "2", "3")) val secondSeq = Some(Seq("car", "dog", "cat"))
目前我使用Slick查询Oracle数据库,代码如下:
(for { number <- numbers .filterOpt(firstSeq)((table, gs) => table.count.inSetBind(gs) && table.type === NumberType.Numeric) .filterOpt(secondSeq)((table, rs) => table.count.inSetBind(rs) && table.type === NumberType.String) } yield { number }).result
请问是否有办法将这两个filterOpt方法合并为一个,实现OR逻辑的查询条件?
解决方案
当然可以,核心思路是将两个可选序列对应的条件组合成一个可选的复合OR条件,再通过一次filterOpt应用到查询上,避免多次链式调用。
模式匹配实现(清晰直观)
通过模式匹配处理两个Option的所有组合情况,生成对应的复合条件:
// 定义复合可选条件 val combinedCondition = (firstSeq, secondSeq) match { case (Some(gs), Some(rs)) => Some((table: NumberTable) => (table.count.inSetBind(gs) && table.type === NumberType.Numeric) || (table.count.inSetBind(rs) && table.type === NumberType.String) ) case (Some(gs), None) => Some((table: NumberTable) => table.count.inSetBind(gs) && table.type === NumberType.Numeric) case (None, Some(rs)) => Some((table: NumberTable) => table.count.inSetBind(rs) && table.type === NumberType.String) case (None, None) => None } // 应用复合条件到查询 numbers.filterOpt(combinedCondition)(_ apply _).result
简化写法(利用Option操作符)
如果觉得模式匹配冗余,可以先把每个序列转换成对应的可选条件,再组合成OR逻辑:
// 先将每个可选序列转为可选条件 val firstCondition = firstSeq.map(gs => (table: NumberTable) => table.count.inSetBind(gs) && table.type === NumberType.Numeric ) val secondCondition = secondSeq.map(rs => (table: NumberTable) => table.count.inSetBind(rs) && table.type === NumberType.String ) // 组合两个可选条件为OR逻辑 val combinedCondition = (firstCondition, secondCondition) match { case (Some(c1), Some(c2)) => Some(c1 || c2) case (existing @ Some(_), None) => existing case (None, existing @ Some(_)) => existing case _ => None } // 执行查询 numbers.filterOpt(combinedCondition)(_ apply _).result
逻辑说明
- 当两个序列都存在时,生成
(条件1) || (条件2)的复合过滤逻辑; - 仅单个序列存在时,直接使用该序列对应的过滤条件;
- 两个序列都不存在时,不添加任何过滤条件,返回全量数据。
这样既实现了OR逻辑的合并,又保留了filterOpt原本的可选过滤特性,代码结构更简洁。
内容的提问来源于stack exchange,提问作者M. Barabas
相关产品推荐
相关产品推荐

