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
}