我正在使用 postgresql 9.6、slick 3.2 并连接了slick-pg。
我在 Scala 中实现了一个 graphql 后端,我需要实现查询来解析各种形状的 GraphQL 游标。输入的形状是可枚举的。影响查询的一些输入可能是:
- 用户可选择的排序。
- 各种过滤条件(全文搜索、日期范围等)。
- 在向后或向前遍历之间进行选择。
我当前的简单游标将向后和向前硬编码为编译查询。两者都具有相同的形状,并且我使用标准的光滑抽象来分解共性以供重用(具有操作的值类、“实体”表的继承层次结构和代码生成)。但是仍然有很多样板,除非我将它们全部列出,否则它不会扩展到更动态的形状。
这是使用此模式的类的摘录:
private [shard] class SchemaAllTypeCursor(shard: SlickShard) extends CursorSpec[TypeModel] {
import shard.PostgresProfile.api._
private val forwardQC = Compiled { (tenantIdUrls: Rep[List[String]], low: Rep[Long], take: ConstColumn[Long]) =>
Queries.listTypesByTenantIds(tenantIdUrls).forwardCursorById(low, take)
}
private val backwardQC = Compiled { (tenantIdUrls: Rep[List[String]], high: Rep[Long], take: ConstColumn[Long]) =>
Queries.listTypesByTenantIds(tenantIdUrls).backwardCursorById(high, take)
}
def executor(tenantIdUrls: List[String])(c: CursorRequest)(implicit req: Req[_]): Observable[TypeModel] = {
implicit val ec = req.ctx.ec
Observable fromFuture {
shard.db.run {
if (c.forward) forwardQC(tenantIdUrls, c.base, c.take).result
else backwardQC(tenantIdUrls, c.base, c.take).result
} flatMap materializeAllTypes(req.ctx, tenantIdUrls)
} flatMap Observable.fromIterable
}
}
总的问题是如何在没有大量样板的情况下获得此用例的编译查询?我想获得的一些见解是:
- 我有什么抽象来组成查询的一部分?在上面的示例中,
backwardCursorById
andforwardCursorById
是查询的一部分。我希望能够从部件构建编译函数并以某种方式缓存它们...... - 如何在编译函数中使用记录类型?(在光滑的文档中暗示这是可能的,但我找不到示例)。
- 有没有办法缓存已编译的查询而不列出它们? - AFAIK。如果我在上面的 executor 函数中编译一个函数,它将在 executor 函数的每个函数调用上重复编译。
我愿意使用 slick-pg 支持的 postgres 特定类型。