gpt4 book ai didi

scala - 灵活查询优化

转载 作者:行者123 更新时间:2023-12-04 03:21:20 25 4
gpt4 key购买 nike

我有以下 Scala/Slick/PlayFramework 代码:

class UserRepository @Inject()(dbConfigProvider: DatabaseConfigProvider, loginInfoRepository: LoginInfoRepository) extends BaseRepository[UserTable, User](TableQuery[UserTable], dbConfigProvider.get[JdbcProfile].db) with UserQuery {

val db = dbConfigProvider.get[JdbcProfile].db
def findUserByProviderIdAndKey(providerId: String, providerKey: String): Future[User] = {
for {
maybeLoginInfo <- loginInfoRepository.findByProviderIdAndProviderKey(providerId, providerKey)
maybeUser <- db.run(query.filter(_.loginId === maybeLoginInfo.loginId).result.head) //query refers to the user table with a loginId column
} yield maybeUser

}

查询用户表和登录信息表。 user 表在 login_info 表中有一个外键。

目前,findByProviderIdAndProviderKey 方法返回一个 Future[LoginInfo]。但是,我想将其更改为为不存在的用户 ID 返回 Future[Option[LoginInfo]]。它可以在 findByProviderIdAndProviderKey 方法中轻松更改,但我不确定理解如何更改以处理选项值。

我想我可以像下面这样(需要重构):

    class UserRepository @Inject()(dbConfigProvider: DatabaseConfigProvider, loginInfoRepository: LoginInfoRepository) extends BaseRepository[UserTable, User](TableQuery[UserTable], dbConfigProvider.get[JdbcProfile].db) with UserQuery {

val db = dbConfigProvider.get[JdbcProfile].db
def findUserByProviderIdAndKey(providerId: String, providerKey: String): Future[User] = {
loginInfoRepository.findByProviderIdAndProviderKey(providerId, providerKey).map{
case (Some(x)) => db.run(query.fitler(_.loginId == x.loginInd).result.headOption)
case None=> Option(None)
}

现在,我有以下问题:

  1. 您将如何处理给定查询不返回值的查询?例如,如果表中不存在登录信息?我做的对吗?或者,还有更好的方法?

  2. 我原以为 slick 会自动满足连接中的 Option 值,但似乎并非如此。为什么 Option 值没有提升?

  3. 是否可以将上面的语句转化为两个 SQL 查询和数据库调用?如果是,我该如何重新构造它,使其仅发出一个具有正确连接的数据库调用?

提前致谢!

最佳答案

由于您只发布了部分代码,我将尝试根据您的问题构建一个示例。

根据您的问题,loginInfoRepository.findByProviderIdAndProviderKey 返回一个 Future[LoginInfo],这意味着您已经在该方法中调用了 db.run。所以要回答第 3 点:是的,因为您两次调用 db.run,所以它会导致两次往返数据库。

Slicks 查询是可组合的,所以您可能想要做的是,在 findUserByProviderIdAndKey 中使用 findByProviderIdAndProviderKey 的查询,而不是结果:

def findUserByProviderIdAndKey(providerId: String, providerKey: String): Future[Option[User]] = {
val userQuery = for {
loginInfo <- loginInfoQuery if loginInfo.providerId === providerId && loginInfo.providerKey === providerKey
user <- query if user.loginId === loginInfo.loginId
} yield user

db.run( userQuery.result.headOption )
}

for comprehension 中的第一行使用给定参数查询所有 LoginInfos(我猜到了您的查询和字段名称)。第二行获取那些 LoginInfos 并使用给定的 loginId 查询 Users

现在如果 loginInfoQuery 没有返回任何东西,第二行将永远不会被执行(for comprehension 的本质)并且 slick 什么也不会返回。如果第一行返回了一些东西,但是没有 User 给定的 loginId,slick 也不会返回任何东西。只有当两行都返回一些东西时,slick 才会真正返回值。

要从结果集中返回一个选项,您可以使用 userQuery.result.headOption。你不应该使用 userQuery.result.head 除非你 100% 肯定会返回一些东西(你通常永远不可能)。

这个查询只会访问数据库一次,并且可能会导致一个连接查询(您需要查看创建的语句,以确保)。

关于scala - 灵活查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38121072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com