如何在 Slick 中正确构建基于多级连接的对象图?

How correctly built an object graph based on multi level join in Slick?

我的模型结构如下:

Group -> Many Parties -> Many Participants

在 API 个通话中,我需要获得带有派对的单个群组,并且它是附加的参与者。

整个结构建立在 4 个表上:

自然地,SQL 是一个非常直接的连接,结合了所有这些。而这正是我想用 slick 做的。 Mu 方法是 dao class 看起来像这样:

def findOneByKeyAndAccountIdWithPartiesAndParticipants(key: UUID, accountId: Int): Future[Option[JourneyGroup]] = {
    val joins = JourneyGroups.groups join
                Parties.parties on (_.id === _.journeyGroupId) joinLeft
                PartiesParticipants.relations on (_._2.id === _.partyId) joinLeft
                Participants.participants on (_._2.map(_.participantId) === _.id)

    val query = joins.filter(_._1._1._1.accountId === accountId).filter(_._1._1._1.key === key)

    val q = for {
      (((journeyGroup, party), partyParticipant), participant) <- query
    } yield (journeyGroup, party, participant)

    val result = db.run(q.result)

    result ????
  }

这里的问题是 resultFuture[Seq[(JourneyGroup, Party, Participant)]]

的类型

然而,我真正需要的是Future[Option[JourneyGroup]]

注意:JourneyGroupParty 的案例 class 有定义的子序列:

case class Party(id: Option[Int] = None,
                 partyType: Parties.Type.Value,
                 journeyGroupId: Int,
                 accountId: Int,
                 participants: Seq[Participant] = Seq.empty[Participant])

case class JourneyGroup(id: Option[Int] = None,
                        key: UUID,
                        name: String,
                        data: Option[JsValue],
                        accountId: Int,
                        parties: Seq[Party] = Seq.empty[Party])

所以他们都可以抱后代

转换成我需要的结果的正确方法是什么?还是我完全走错了方向?

另外,这个说法对吗: Participants.participants on (_._2.map(_.participantId) === _.id) ?

我最终做了这样的事情:

journeyGroupDao.findOneByKeyAndAccountIdWithPartiesAndParticipants(key, account.id.get) map { data =>

      val groupedByJourneyGroup = data.groupBy(_._1)

      groupedByJourneyGroup.map { case (group, rows) =>

        val parties = rows.map(_._2).distinct map { party =>
          val participants = rows.filter(r => r._2.id == party.id).flatMap(_._3)

          party.copy(participants = participants)

        }

          group.copy(parties = parties)

      }.headOption

    }

其中 DAO 方法的签名是:

def findOneByKeyAndAccountIdWithPartiesAndParticipants(key: UUID, accountId: Int): Future[Seq[(JourneyGroup, Party, Option[Participant])]]