Scala光滑接头左侧和组合条件

Scala光滑接头左侧和组合条件,scala,playframework,slick,Scala,Playframework,Slick,我希望能够使用Slick创建一个查询,以便以动态方式过滤左连接 case class Player( id: Long, createdAt: DateTime, lastModificationDate: DateTime, name: String ) class PlayerTable(tag: Tag) extends Table[Player](tag, "players") { def id = column[Long]("id", O.PrimaryKey,

我希望能够使用
Slick
创建一个查询,以便以动态方式过滤左连接

case class Player(
  id: Long,
  createdAt: DateTime,
  lastModificationDate: DateTime,
  name: String
)

class PlayerTable(tag: Tag)  extends Table[Player](tag, "players") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def createdAt = column[DateTime]("createdAt")
  def lastModificationDate = column[DateTime]("lastModificationDate")
  def name = column[String]("name")
  override def * : ProvenShape[Player] = (
  id,
  createdAt,
  lastModificationDate,
  updatedAt,
  name
  ) <> (Player.tupled, Player.unapply)
}

case class PlayerGame(
  id: Long,
  createdAt: DateTime,
  lastModificationDate: DateTime,
  playerId: Long,
  level: Int,
  status: String
)

class PlayerGameTable(tag: Tag)  extends Table[PlayerGame](tag, "player_games") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def createdAt = column[DateTime]("createdAt")
  def lastModificationDate = column[DateTime]("lastModificationDate")
  def playerId = column[Long]("playerId")
  def level = column[Int]("level")
  def status = column[String]("status")
  override def * : ProvenShape[PlayerGame] = (
  id,
  createdAt,
  lastModificationDate,
  playerId,
  level,
  status
  ) <> (PlayerGame.tupled, PlayerGame.unapply)
}
我尝试过类似的方法,但是我得到了
Rep[Option[PlayerGameTable]]
作为参数。也许有一种不同的方式来做这样的事情

val baseQuery = for {
  ((p, g1), g2) <- PlayerTable.playerQuery joinLeft 
    PlayerGameTable.playerGameQuery ON ((x, y) => x.id === y.playerId && y.level === 1) joinLeft
    PlayerGameTable.playerGameQuery ON ((x, y) => x._1.id === y.playerId && y.level === 2)
} yield (p, g1, g2)

private def filterPlayerGames(gameStatus: String, playerGamesOneOpt: Option[PlayerGameTable], playerGamesTwoOpt: Option[PlayerGameTable]) = {
  (gameStatus, playerGamesOneOpt, playerGamesOneOpt) match {
    case (gameStatus: String, Some(playerGamesOne: PlayerGameTable), Some(playerGamesOne: PlayerGameTable)) if gameStatus == "gameOver"  => playerGamesOne.status === "gameOver" || playerGamesTwo.status === "gameOver"
 }
}
val baseQuery=for{
(p,g1),g2)x.id==y.playerId和&y.level==1)左
PlayerGameTable.playerGameQuery ON((x,y)=>x.\u 1.id==y.playerId&&y.level==2)
}产量(p、g1、g2)
私有def filterPlayerGames(游戏状态:String,playerGamesOneOpt:Option[PlayerGameTable],playerGamesTwoOpt:Option[PlayerGameTable])={
(游戏状态、玩家角色名称、玩家角色名称)匹配{
案例(gameStatus:String,一些(playerGamesOne:PlayerGameTable),一些(playerGamesOne:PlayerGameTable)),如果gameStatus==“gameOver”=>playerGamesOne.status==“gameOver”| | playerGamesTwo.status==“gameOver”
}
}

这是一个复杂的问题,如果问题不清楚,请让我知道,我将尝试澄清这一点。有几个问题:

  • 在多个条件下,在
    ON
    子句中使用的
    下划线
    占位符将无法按预期方式工作
  • \uuu.level=something
    是一个赋值,而不是一个条件
  • 假设
    PlayerTable.playerQuery
    TableQuery[PlayerTable]
    PlayerGameTable.playergametquery
    TableQuery[PlayerGameTable]
    ,则您的
    baseQuery
    应如下所示:

    val baseQuery = for {
      ((p, g1), g2) <- PlayerTable.playerQuery joinLeft 
        PlayerGameTable.playerGameQuery on ((x, y) => x.id === y.playerId && y.level === 1) joinLeft
        PlayerGameTable.playerGameQuery on ((x, y) => x._1.id === y.playerId && y.level === 2)
    } yield (p, g1, g2)
    
    注意,对于
    左连接
    s,
    g1
    g2
    为选项类型,因此
    已定义
    用于
    操作


    另一方面,考虑到您的筛选条件仅在
    PlayerGameTable
    上,在
    加入之前执行
    筛选
    可能会更有效。

    谢谢您的回答。我改变了我的提问错误,你的回答对我来说很有意义。我正在努力让它工作。我不确定我犯了什么错误,例如,在
    查询1
    中,
    ===
    无法解决。我想问题在于
    joinLeft
    ,我不确定,但我认为这就是我无法过滤条件的原因。Slick无法解析
    =
    或类似
    的问题。我得到
    value===不是slick.lifted.Rep[Option[Option[String]]]
    非常感谢您的帮助。我想问题可能是在
    过滤器中
    我没有
    选项[PlayerGame]
    我有
    Rep[Option[PlayerGame]]
    也许这就是为什么
    ====
    没有被识别的原因,这对你有意义吗?@agusgambina,对不起,我过度简化了过滤查询。答案已更新。@agusgambina,仅供参考,过滤查询已简化/重构。
    val baseQuery = for {
      ((p, g1), g2) <- PlayerTable.playerQuery joinLeft 
        PlayerGameTable.playerGameQuery on ((x, y) => x.id === y.playerId && y.level === 1) joinLeft
        PlayerGameTable.playerGameQuery on ((x, y) => x._1.id === y.playerId && y.level === 2)
    } yield (p, g1, g2)
    
    val query1 = baseQuery.filter{ case (_, g1, g2) =>
      g1.filter(_.status === "gameOver").isDefined || g2.filter(_.status === "gameOver").isDefined
    }
    
    val query2 = baseQuery.filter{ case (_, g1, g2) =>
      g1.filter(_.status === "playing").isDefined || g2.filter(_.status =!= "gameOver").isDefined
    }