如何在 slick 中过滤 Option[Boolean] 列
How to filter on a Option[Boolean] column in slick
我的数据库中有以下列,这是一个布尔值,但也接受 NULL,因此 true、false 和 NULL 都是有效的:
def rtb = column[Option[Boolean]]("rtb")
并有以下来自客户端的可选输入,我想过滤:
rtbFromClient: Option[Boolean] = ...
我有以下内容(基于这个关于如何在 slick 中进行查询的答案:):
val query = userTable.
filter(row =>
if (rtbFromClient.isDefined)
row.rtb.get === rtbFromClient.get
else
LiteralColumn(true)
)
但是当代码运行时出现这个错误:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
我认为这可能是因为 row.rtb.get 在调用 get 时抛出异常,因为数据库中的值为空,所以尝试将其更改为 row.rtb.getOrElse(null) 和 row.rtb.getOrElse(None) 但这些都不起作用)
还尝试了以下方法:
if (rtbFromClient.isDefined) {
val query = query.filter(_.rtb.isDefined).filter(_.rtb.get === rtbFromClient.get)
}
但这也会在运行时引发相同的错误:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
总结一下:
- 我的数据库中有一个 Option[Boolean] 列,它可以包含 true、false 或 NULL(实际 mysql 类型是一个 tinyint(1),映射到一个灵活的 Option[Boolean] )
- 我有一个由用户提供的可选过滤器 rtbFromClient,如果存在,我想对其进行过滤。如果存在,这将是 true 或 false
- 我还有其他具有类似行为的可选过滤器(此处未显示),因此我希望能够轻松组合它们
首先检查该列是否为空,然后继续进行另一次比较。确保 rtbFromClient
不是一个选项。
val query = userTable.filter(row => !row.rtb.isEmpty &&
row.rtb === rtbFromClient)
第一个条件确保过滤空值,第二个条件检查值以防列值不为空。
如果您有可选值,那么下面的代码会有所帮助。
def query(value: Option[Boolean]) = value match {
case Some(userGivenRtbFromClient) =>
userTable.filter(row => !row.rtbFromClient.isNull &&
row.rtbFromClient === userGivenRtbFromClient)
case None => userTable.filter(row => row.rtbFromClient.isNull)
}
更干净的版本在这里。
rtbFromClient: Option[Boolean]
rtbFromClient
用户给出了可选值以与 slick 列进行比较。
userTable.filter(row => rtbFromClient.map(value => row.rtb === Some(value): Option[Boolean]).getOrElse(row.rtb.isEmpty))
var query = userTable.drop(page.skip).take(page.top)
if (rtbFromClient.isDefined) {
query = query.filter(row => row.rtb.isDefined && row.rtb === rtbFromClient)
}
// More if blocks with optional filters here
...
dbProvider.db.run(query.result)
试试这个
val query = userTable.filter(row => rtbFromClient.map(x => Option(x) === row.rtb).getOrElse(row.rtb.isEmpty.?))
我遇到了同样的问题。玩了之后我意识到可以直接按选项过滤,所以如果我们有列
def rtb = column[Option[Boolean]]("rtb")
我们正在尝试按
过滤
rtbFromClient: Option[Boolean] = ...
那么我们可以这样做:
val query: DBIO[Seq[TableElementType]] =
if (rtbFromClient.isDefined)
userTable.filter(_.rtb === rtbFromClient).result
else
userTable.result
我遇到了同样的问题。我的解决方案是(使用 Slick 3 测试。3.x):
val query = usersTable.filterOpt(rtbFromClient)(_.rtb === _)
情况一(当rtbFromClient为空时)对应如下SQL:
select * from users;
情况二(定义了rtbFromClient):
select * from users where rtb = ?;
我的数据库中有以下列,这是一个布尔值,但也接受 NULL,因此 true、false 和 NULL 都是有效的:
def rtb = column[Option[Boolean]]("rtb")
并有以下来自客户端的可选输入,我想过滤:
rtbFromClient: Option[Boolean] = ...
我有以下内容(基于这个关于如何在 slick 中进行查询的答案:
val query = userTable.
filter(row =>
if (rtbFromClient.isDefined)
row.rtb.get === rtbFromClient.get
else
LiteralColumn(true)
)
但是当代码运行时出现这个错误:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
我认为这可能是因为 row.rtb.get 在调用 get 时抛出异常,因为数据库中的值为空,所以尝试将其更改为 row.rtb.getOrElse(null) 和 row.rtb.getOrElse(None) 但这些都不起作用)
还尝试了以下方法:
if (rtbFromClient.isDefined) {
val query = query.filter(_.rtb.isDefined).filter(_.rtb.get === rtbFromClient.get)
}
但这也会在运行时引发相同的错误:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
总结一下:
- 我的数据库中有一个 Option[Boolean] 列,它可以包含 true、false 或 NULL(实际 mysql 类型是一个 tinyint(1),映射到一个灵活的 Option[Boolean] )
- 我有一个由用户提供的可选过滤器 rtbFromClient,如果存在,我想对其进行过滤。如果存在,这将是 true 或 false
- 我还有其他具有类似行为的可选过滤器(此处未显示),因此我希望能够轻松组合它们
首先检查该列是否为空,然后继续进行另一次比较。确保 rtbFromClient
不是一个选项。
val query = userTable.filter(row => !row.rtb.isEmpty &&
row.rtb === rtbFromClient)
第一个条件确保过滤空值,第二个条件检查值以防列值不为空。
如果您有可选值,那么下面的代码会有所帮助。
def query(value: Option[Boolean]) = value match {
case Some(userGivenRtbFromClient) =>
userTable.filter(row => !row.rtbFromClient.isNull &&
row.rtbFromClient === userGivenRtbFromClient)
case None => userTable.filter(row => row.rtbFromClient.isNull)
}
更干净的版本在这里。
rtbFromClient: Option[Boolean]
rtbFromClient
用户给出了可选值以与 slick 列进行比较。
userTable.filter(row => rtbFromClient.map(value => row.rtb === Some(value): Option[Boolean]).getOrElse(row.rtb.isEmpty))
var query = userTable.drop(page.skip).take(page.top)
if (rtbFromClient.isDefined) {
query = query.filter(row => row.rtb.isDefined && row.rtb === rtbFromClient)
}
// More if blocks with optional filters here
...
dbProvider.db.run(query.result)
试试这个
val query = userTable.filter(row => rtbFromClient.map(x => Option(x) === row.rtb).getOrElse(row.rtb.isEmpty.?))
我遇到了同样的问题。玩了之后我意识到可以直接按选项过滤,所以如果我们有列
def rtb = column[Option[Boolean]]("rtb")
我们正在尝试按
过滤rtbFromClient: Option[Boolean] = ...
那么我们可以这样做:
val query: DBIO[Seq[TableElementType]] =
if (rtbFromClient.isDefined)
userTable.filter(_.rtb === rtbFromClient).result
else
userTable.result
我遇到了同样的问题。我的解决方案是(使用 Slick 3 测试。3.x):
val query = usersTable.filterOpt(rtbFromClient)(_.rtb === _)
情况一(当rtbFromClient为空时)对应如下SQL:
select * from users;
情况二(定义了rtbFromClient):
select * from users where rtb = ?;