gpt4 book ai didi

scala - 如何使用 Slick 3.0 编写可读的嵌套连接查询

转载 作者:行者123 更新时间:2023-12-05 00:54:51 24 4
gpt4 key购买 nike

此代码正在创建一个查询,用于在 Web 后端检索用户的个人资料。它创建一个查询,将必要的信息组合成一个 DTO(它只是一个案例类),随后作为 JSON 发回。

  def getProfile(userId: Long)={
val q = for{
((((u,p),a),b), ba) <- filterById(userId) join
People on (_.personId === _.id) joinLeft
Addresses on (_._2.addressId === _.id) joinLeft
Businesses on (_._1._2.businessId === _.id) joinLeft
Addresses on (_._2.flatMap(_.addressId) === _.id)
}yield(p, a, b, ba)

db.run(q.result.headOption).map{ _.map{case(p,a,b,ba) =>
val business = b match {
case Some(b) => Some(dtos.Business(b.name, b.abn, b.adminFee, ba, b.id))
case _ => None
}

dtos.ProfileInfo(p, a, business)
}}
}

我已经包含了仅用于上下文的结果处理( db.run(...) )。

我正在寻找一种更具可读性的方式来表达查询构造。

我阅读这篇文章的经验是“等等,什么?? ... on (_._1._2.flatMap(_.addressId) ....那在做什么??为什么在那里而不是在这里进行平面映射: on (_._1._2.businessId。这些实际上是直截了当的事情,但不要阅读直截了当。

我正在寻找一种表达方式,不需要阅读此版本所需的扣除量。我必须“推断” _._1._2 是什么,以及为什么需要将其展平,这与等效的 SQL 无关。

笔记:
  • 此代码来自我正在扩展的现有应用程序(不是我编写的)。
  • 用户、人员、地址、企业是(显然?)表。
  • 人和企业都有地址。
  • 用户有一个人(*),人有一个业务
  • filterByUserId(userId)基本上相当于Users.filter(_.id === userId )
  • 等效的 SQL 是:
    select p.*, a1.*, b.*, a2.* from Users u 
    innerJoin People p on (u.personId == p.id)
    leftJoin Addresses a1 on (p.addressId == a1.id)
    leftJoin Businesses b on (p.businessId == b.id)
    leftJoin Addresses a2 on ( b.addressId == a2.id)
  • 最佳答案

    你应该尝试这样的事情:

    val q = Users join People joinLeft Addresses joinLeft Businesses joinLeft Addresses on {
    case ((((u, p), a), b), ba) => u.personId === p.id && p.addressId === a.flatMap(_.id) && p.businessId === b.flatMap(_.id) && b.flatMap(_.addressId) === ba.id
    } map {
    case ((((u, p), a), b), ba) => (p, a, b, ba)
    }

    另一种解决方案是在不使用理解的情况下进行连接,因此您不必使用下划线从元组中提取值:
    val q = Users join People on {
    case (u, p) => u.personId === p.id
    } joinLeft Addresses on {
    case ((u, p), a) => p.addressId === a.id
    } joinLeft Businesses on {
    case (((u, p), a), b) => p.businessId === b.id
    } joinLeft Addresses on {
    case ((((u, p), a), b), ba) => b.flatMap(_.addressId) === ba.id
    } map {
    case ((((u, p), a), b), ba) => (p, a, b, ba)
    }

    您尚未提供数据的完整定义,因此我无法完全测试这些解决方案,但这应该能让您深入了解在 Slick 中定义连接的不同方式。让我知道这是否有帮助。

    关于scala - 如何使用 Slick 3.0 编写可读的嵌套连接查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39120860/

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