Slick:有没有办法用正则表达式创建WHERE子句?

时间:2017-09-14 11:38:45

标签: regex scala slick

我寻找与

等同的光滑
select * from users where last_name ~* '[\w]*son';

例如,当在数据库中具有以下名称时:

first_name | last_name
----------------------
Tore       | Isakson
John       | Smith
Solveig    | Larsson
Marc       | Finnigan

结果将是

first_name | last_name
----------------------
Tore       | Isakson
Solveig    | Larsson

我目前的解决方案是使用像

这样的SQLActionBuilder插入它
val pattern = "[\\w]*son"
val action = sql""" SELECT * FROM users WHERE last_name ~* ${pattern}; """.as[User]

但这不是我希望拥有它的方式。我更喜欢像

这样的东西
users.filter(_.last_name matchRegex "[\\w]*son")   // <- This does not exist

如果相关:我使用Postgres。

1 个答案:

答案 0 :(得分:3)

(这个答案是关注Slick: How can I combine a SQL LIKE statement with a SQL IN statement

中的问题

虽然Slick不支持开箱即用的SimpleExpression运算符,但您可以自行添加它。这将为您提供一种使用提升的嵌入式样式的Slick查询来执行查询的方法。

为此,您可以使用def find(names: Seq[String]): DBIO[Seq[String]] = { val pattern = names.mkString("|") users.filter(_.lastName regexLike pattern).map(_.lastName).result } 构建器。关于它的文档不多,但跳出点将是参考手册的Scalar Database Functions页面。

我们想要做的是按照以下方式编写方法:

regexLike

要获得regexLike,我们可以使用字符串列富集(增强,“pimp”)来获得implicit class RegexLikeOps(s: Rep[String]) { def regexLike(p: Rep[String]): Rep[Boolean] = { val expr = SimpleExpression.binary[String,String,Boolean] { (s, p, qb) => qb.expr(s) qb.sqlBuilder += " ~* " qb.expr(p) } expr.apply(s,p) } } 方法:

implicit class

RegexLikeOps部分允许编译器在Rep[String]类具有Rep[String]时调用regexLike尚未拥有的方法(即,当regexLike被要求时。

我们的Rep[String]方法将另一个SimpleExpression参数作为模式,然后使用val program = for { _ <- users.schema.create _ <- users ++= User("foo") :: User("baz") :: User("bar") :: Nil result <- find( Seq("baz","bar") ) } yield result println( Await.result(db.run(program), 2.seconds) ) 构建器安全地构造我们想要使用的SQL。

把它们放在一起我们可以写:

select "last_name" from "app_user" where "last_name" ~* 'baz|bar'

生成的SQL(在我的H2测试中)是:

new Test().Func2()

完整代码为:https://github.com/d6y/so46199828