此代码正在创建一个查询,用于在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(...)
)仅包含在上下文中。
我正在寻找一种更易读的方式来表达查询结构。
我阅读这篇文章的经历是&#34;等等,什么? ...... on (_._1._2.flatMap(_.addressId)
....那是做什么的?为什么要平面图而不是这里:on (_._1._2.businessId
。这些实际上是直接的东西,但不要直接读到。
我正在寻找一种表达方式,并不需要阅读此版本所需的扣除金额。我必须&#34;演绎&#34;什么是_._ 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)
答案 0 :(得分:5)
你应该尝试这样的事情:
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)
}
另一个解决方案是在不使用for comprehension的情况下进行连接,因此您不必使用下划线从元组中提取值:
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中定义联接的不同方法。让我知道这是否有用。