光滑的 groupBy 中的任何字符串连接方法?
Any string concatenation method in slick groupBy?
我正在尝试在 Slick 查询中应用 .groupBy
var q = (for {
user <- Users
userSettings <- UserSettings if user.id === userSettings.userId
} yield (user, userSettings)).groupBy {
case (users, userSettings) =>
(user.id, userSettings.controls)
}.map {
case (x, y) => (x._1, y.map(_._2.controls).???)
}
如果 controls
列是 Integer 或 Long,我可以应用 sum
、avg
和其他聚合函数。但在这种情况下 controls
是一个字符串。如何分组连接这些字符串,使记录看起来像
-----------------------------------------
|User ID |User Controls |
-----------------------------------------
|1 |left, right, up, down |
|2 |left, right |
-----------------------------------------
不应用 groupBy
记录如下所示
-----------------------------------------
|User ID |User Controls |
-----------------------------------------
|1 |left |
|1 |right |
|1 |up |
|1 |down |
|2 |left |
|2 |right |
-----------------------------------------
Slick 获取您的 Scala 代码并将其转换为 SQL,因此您在 Slick 中所做的任何事情都必须得到底层 SQL 的支持。如果您在 SQL 中搜索与连接字符串相关的类似问题,您 find some results on SO。不幸的是,在 SQL 中做这种事情并非易事。 (注意:在某些 SQL 方言中是可能的。)可能有一些 Slick 驱动程序公开了 SQL-方言特定的功能,或者在SQL 查询,但您可以简单地获取您的查询,然后 运行 groupBy/map 在对数据库执行它之后,例如:
val q = for {
user <- Users
userSettings <- UserSettings if user.id === userSettings.userId
} yield (user.id, userSettings.controls)
val db = Database.forConfig("h2mem1")
try {
for {
res <- db.run(q.result)
} yield res
.groupBy(_._1)
.map({ case (id, t) => id -> t.map(_._2).mkString(", ") })
} finally db.close
不幸的是,没有注意到对此的支持。在这种情况下,我们可以使用经过适当验证和清理的原始查询。
假设,我有一个名为 logs
(id、消息、日期)的 table。我想按日期分组并联系每个组消息。所以我的查询将是:
def histogram(data: ReqData): Future[Vector[DbHistogramMapper]] = {
var messageWild = s"%${data.phrase}%"
/**Need to write raw query because there is no support for GROUP_CONCAT in slick*/
val query = sql"""SELECT "date" AS date, GROUP_CONCAT("message") AS message FROM "logs" WHERE "date" >= ${data.datetimeFrom} AND "date" <= ${data.datetimeUntil} AND "message" LIKE ${messageWild} GROUP BY "date" """.as[DbHistogramMapper]
db.run(query)
}
注:DbHistogramMapper
case class DbHistogramMapper(
date: Timestamp,
message: String
)
我正在尝试在 Slick 查询中应用 .groupBy
var q = (for {
user <- Users
userSettings <- UserSettings if user.id === userSettings.userId
} yield (user, userSettings)).groupBy {
case (users, userSettings) =>
(user.id, userSettings.controls)
}.map {
case (x, y) => (x._1, y.map(_._2.controls).???)
}
如果 controls
列是 Integer 或 Long,我可以应用 sum
、avg
和其他聚合函数。但在这种情况下 controls
是一个字符串。如何分组连接这些字符串,使记录看起来像
-----------------------------------------
|User ID |User Controls |
-----------------------------------------
|1 |left, right, up, down |
|2 |left, right |
-----------------------------------------
不应用 groupBy
记录如下所示
-----------------------------------------
|User ID |User Controls |
-----------------------------------------
|1 |left |
|1 |right |
|1 |up |
|1 |down |
|2 |left |
|2 |right |
-----------------------------------------
Slick 获取您的 Scala 代码并将其转换为 SQL,因此您在 Slick 中所做的任何事情都必须得到底层 SQL 的支持。如果您在 SQL 中搜索与连接字符串相关的类似问题,您 find some results on SO。不幸的是,在 SQL 中做这种事情并非易事。 (注意:在某些 SQL 方言中是可能的。)可能有一些 Slick 驱动程序公开了 SQL-方言特定的功能,或者在SQL 查询,但您可以简单地获取您的查询,然后 运行 groupBy/map 在对数据库执行它之后,例如:
val q = for {
user <- Users
userSettings <- UserSettings if user.id === userSettings.userId
} yield (user.id, userSettings.controls)
val db = Database.forConfig("h2mem1")
try {
for {
res <- db.run(q.result)
} yield res
.groupBy(_._1)
.map({ case (id, t) => id -> t.map(_._2).mkString(", ") })
} finally db.close
不幸的是,没有注意到对此的支持。在这种情况下,我们可以使用经过适当验证和清理的原始查询。
假设,我有一个名为 logs
(id、消息、日期)的 table。我想按日期分组并联系每个组消息。所以我的查询将是:
def histogram(data: ReqData): Future[Vector[DbHistogramMapper]] = {
var messageWild = s"%${data.phrase}%"
/**Need to write raw query because there is no support for GROUP_CONCAT in slick*/
val query = sql"""SELECT "date" AS date, GROUP_CONCAT("message") AS message FROM "logs" WHERE "date" >= ${data.datetimeFrom} AND "date" <= ${data.datetimeUntil} AND "message" LIKE ${messageWild} GROUP BY "date" """.as[DbHistogramMapper]
db.run(query)
}
注:DbHistogramMapper
case class DbHistogramMapper(
date: Timestamp,
message: String
)