2017-09-14 46 views
0

我找了一個漂亮的equivalient到油滑:有沒有辦法用正則表達式創建一個WHERE子句?

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。

回答

2

(這個答案是繼Slick: How can I combine a SQL LIKE statement with a SQL IN statement問題)

雖然油滑不支持~*運營商開箱,你可以自己添加。這將給你一個方法來執行查詢使用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我們可以使用一個充實(增強,「皮條客」)的字符串列有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類隨時隨地它有一個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' 

完整的代碼是:https://github.com/d6y/so46199828

相關問題