如何解决如何在Slick中过滤部分索引的布尔列? 变化1 变化2 版本3
我有一个用Slick查询的Postgres数据库。问题是我有一个被索引(部分索引)的BOOLEAN列(archived
)。我通过EXPLAIN / ANALYZE发现,仅当查询采用WHERE archived IS FALSE
形式时才使用索引,但是Slick似乎只输出WHERE archived = False
或WHERE NOT archived
...我该如何修改我光滑的查询,或者,如果不可能的话,可以更改索引,使其与archived = false
一起使用?这是更多信息:
变化1
光滑
val query = Messages
.filterOpt(isArchived) { (row,archived) =>
if (archived) { row.archived }
else { !row.archived }
}
.sortBy(_.id.desc)
平滑输出
select "id","info","archived" from "messages" where not "archived" order by "id" desc
查询说明
Sort (cost=37988.82..37988.90 rows=33 width=1033)
Sort Key: id DESC
-> Seq Scan on messages (cost=0.00..37987.99 rows=33 width=1033)
Filter: (NOT archived)
变化2
光滑
val query = Messages
.filterOpt(isArchived) { (row,archived) =>
row.archived === archived
}
.sortBy(_.id.desc)
平滑输出
select "id","archived" from "messages" where "archived" = false order by "id" desc
查询说明(与说明1相同)
Sort (cost=37988.82..37988.90 rows=33 width=1033)
Sort Key: id DESC
-> Seq Scan on messages (cost=0.00..37987.99 rows=33 width=1033)
Filter: (NOT archived)
版本3
光滑
???
所需)平滑输出
select "id","archived" from "messages" where "archived" IS false order by "id" desc
(所需)查询说明
Sort (cost=21.67..21.75 rows=33 width=1033)
Sort Key: id DESC
-> Index Scan using messages_archived on messages (cost=0.27..20.84 rows=33 width=1033)
解决方法
不是使用WHERE archived is false
创建我们的部分索引,而是使用WHERE not archived
或WHERE archived = false
创建它。 Postgres似乎很聪明,可以相互转换其中的第二和第三,但不能与其他两个相互转换。
由于这个useful Medium Article,我找到了答案。它涉及扩展Slick PostgresProfile API
// ExtendedPostgresProfile.scala
import slick.ast.Library.SqlOperator
import slick.jdbc.PostgresProfile
import slick.jdbc.PostgresProfile.api._
import slick.lifted.BaseExtensionMethods
import scala.language.implicitConversions
/***
* We need to Extend the PostgresProfile because the standard Slick filter on
* `messages.archived` doesn't utilize the index on that column
* (it uses = instead of IS). This explicitly creates an IS operator
*/
trait ExtendedPostgresProfile extends PostgresProfile {
trait ExtApi extends API {
implicit def extendedBoolColumn(c: Rep[Boolean]): BaseBooleanExtendedBooleanMethods[Boolean] =
new BaseBooleanExtendedBooleanMethods[Boolean](c)
}
override val api: ExtApi = new ExtApi {}
final class BaseBooleanExtendedBooleanMethods[P1](val c: Rep[P1]) extends BaseExtensionMethods[P1] {
def is[P2,R](e: Rep[P2])(implicit om: o#arg[P1,P2]#to[P1,R]) =
om.column(Operators.IS,n,e.toNode)
}
object Operators{
val IS = new SqlOperator("IS")
}
}
object ExtendedPostgresProfile extends ExtendedPostgresProfile
和实际的Slick代码:
// import slick.jdbc.PostgresProfile.api._ <- Removed
import ExtendedPostgresProfile.api._
val query = Messages
.filterOpt(isArchived) { (row,archived) =>
row.archived is archived
}
.sortBy(_.id.desc)
输出是
select "id","info","archived" from "messages" where "archived" IS false order by "id" desc
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。