Slick:有没有办法用正则表达式创建 WHERE 子句?
Slick: Is there a way to create a WHERE clause with a regex?
我想找一个等同于
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。
(此答案在 中的问题之后)
尽管 Slick 不支持开箱即用的 ~*
运算符,但您可以自己添加。这将为您提供一种使用 lifted embedded 样式的 Slick 查询来执行查询的方法。
为此,您可以使用 SimpleExpression
生成器。关于它的文档不多,但起点是参考手册的 Scalar Database Functions 页。
我们想要做的是按照这些思路编写一个方法:
def find(names: Seq[String]): DBIO[Seq[String]] = {
val pattern = names.mkString("|")
users.filter(_.lastName regexLike pattern).map(_.lastName).result
}
要获得 regexLike
我们可以使用丰富(增强,"pimp")字符串列来获得 regexLike
方法:
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
class 它有一个 Rep[String]
调用 Rep[String]
不调用的方法'已经有(即,当要求 regexLike
时)。
我们的 regexLike
方法将另一个 Rep[String]
参数作为模式,然后使用 SimpleExpression
构建器安全地构建我们要使用的 SQL。
把它们放在一起我们可以写成:
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(在我使用 H2 的测试中)是:
select "last_name" from "app_user" where "last_name" ~* 'baz|bar'
我想找一个等同于
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。
(此答案在
尽管 Slick 不支持开箱即用的 ~*
运算符,但您可以自己添加。这将为您提供一种使用 lifted embedded 样式的 Slick 查询来执行查询的方法。
为此,您可以使用 SimpleExpression
生成器。关于它的文档不多,但起点是参考手册的 Scalar Database Functions 页。
我们想要做的是按照这些思路编写一个方法:
def find(names: Seq[String]): DBIO[Seq[String]] = {
val pattern = names.mkString("|")
users.filter(_.lastName regexLike pattern).map(_.lastName).result
}
要获得 regexLike
我们可以使用丰富(增强,"pimp")字符串列来获得 regexLike
方法:
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
class 它有一个 Rep[String]
调用 Rep[String]
不调用的方法'已经有(即,当要求 regexLike
时)。
我们的 regexLike
方法将另一个 Rep[String]
参数作为模式,然后使用 SimpleExpression
构建器安全地构建我们要使用的 SQL。
把它们放在一起我们可以写成:
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(在我使用 H2 的测试中)是:
select "last_name" from "app_user" where "last_name" ~* 'baz|bar'