根据可选值编写更新查询
Compose update query based on optional values
下面的函数有一个 UUID 参数和两个可选参数。根据两个可选参数的状态将决定它们是否包含在更新查询中。
def updateChunkState(chunkId: UUID, state: ChunkState, comment: Option[String], sourceLanguage: Option[String]): Either[ChunkNotFoundError, Unit] = {
val result = (comment, sourceLanguage) match {
case (c: Some[String], s: Some[String]) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state, c.comment, c.sourceLanguage))
exec(query.update(state, comment, sourceLanguage))
}
case (c: Some[String], None) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state, c.comment))
exec(query.update(state, comment))
}
case (None, s: Some[String]) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state, c.sourceLanguage))
exec(query.update(state, sourceLanguage))
}
case (None, None) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state))
exec(query.update(state))
}
}
result match {
case 0 => Left(ChunkNotFoundError(chunkId))
case n if n > 0 => Right(())
}
}
我相信应该有一种方法可以让我的 query/update 比我上面的蛮力尝试更优雅一点,如果有人能启发我,我将不胜感激。
我认为你在 atm 上的做法很好。 4场比赛没有出路。也许让它更优雅的一种方法是将重复代码收集到一个地方,即。您可以在一个地方调用 exec(query.update(...)) 而不是在 4 个地方调用它。在这里我只是将其称为字符串列表,我不知道该函数如何使用可变数量的参数。而不是在 4 个不同的地方过滤它,你可以在开始模式匹配之前过滤一次。只是让它更容易阅读,因为它不是一大段代码。
如果您不使用匹配的元组变量,则无需为它们命名,即 c 和 s。而且也不需要类型,你知道它是来自函数签名的字符串。在那种情况下(我不需要变量)我更喜欢 Some(_),如果你匹配正确的方式,从 (Some, Some) 到 (None, None),使用 _ (通配符) 用于 None 情况,_ 用于 (None, None) 情况
我列出了您用于 query.update() 的所有参数并将它们放入列表中。在 Some() 中包装状态并使用展平来删除 Nones。然后使用 _* 运算符将这些应用于函数。
我认为代码就这样没问题,但你可以像这样删掉 10 行。
def updateChunkState(chunkId: UUID, state: ChunkState, comment: Option[String], sourceLanguage: Option[String]): Either[ChunkNotFoundError, Unit] = {
val updateParams = List(Some(state), comment, sourceLanguage).flatten
val queryFiltered = ChunkTable.query.filter(_.id === chunkId.toString)
val query = (comment, sourceLanguage) match {
case (Some(_), Some(_)) => queryFiltered.map(c => (c.state, c.comment, c.sourceLanguage))
case (Some(_), _) => queryFiltered.map(c => (c.state, c.comment))
case (_, Some(_)) => queryFiltered.map(c => (c.state, c.sourceLanguage))
case _ => queryFiltered.map(c => (c.state))
}
exec(query.update(updateParams:_*)) match {
case 0 => Left(ChunkNotFoundError(chunkId))
case n if n > 0 => Right(())
}
下面的函数有一个 UUID 参数和两个可选参数。根据两个可选参数的状态将决定它们是否包含在更新查询中。
def updateChunkState(chunkId: UUID, state: ChunkState, comment: Option[String], sourceLanguage: Option[String]): Either[ChunkNotFoundError, Unit] = {
val result = (comment, sourceLanguage) match {
case (c: Some[String], s: Some[String]) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state, c.comment, c.sourceLanguage))
exec(query.update(state, comment, sourceLanguage))
}
case (c: Some[String], None) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state, c.comment))
exec(query.update(state, comment))
}
case (None, s: Some[String]) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state, c.sourceLanguage))
exec(query.update(state, sourceLanguage))
}
case (None, None) => {
val query = ChunkTable.query.filter(_.id === chunkId.toString).map(c => (c.state))
exec(query.update(state))
}
}
result match {
case 0 => Left(ChunkNotFoundError(chunkId))
case n if n > 0 => Right(())
}
}
我相信应该有一种方法可以让我的 query/update 比我上面的蛮力尝试更优雅一点,如果有人能启发我,我将不胜感激。
我认为你在 atm 上的做法很好。 4场比赛没有出路。也许让它更优雅的一种方法是将重复代码收集到一个地方,即。您可以在一个地方调用 exec(query.update(...)) 而不是在 4 个地方调用它。在这里我只是将其称为字符串列表,我不知道该函数如何使用可变数量的参数。而不是在 4 个不同的地方过滤它,你可以在开始模式匹配之前过滤一次。只是让它更容易阅读,因为它不是一大段代码。
如果您不使用匹配的元组变量,则无需为它们命名,即 c 和 s。而且也不需要类型,你知道它是来自函数签名的字符串。在那种情况下(我不需要变量)我更喜欢 Some(_),如果你匹配正确的方式,从 (Some, Some) 到 (None, None),使用 _ (通配符) 用于 None 情况,_ 用于 (None, None) 情况
我列出了您用于 query.update() 的所有参数并将它们放入列表中。在 Some() 中包装状态并使用展平来删除 Nones。然后使用 _* 运算符将这些应用于函数。
我认为代码就这样没问题,但你可以像这样删掉 10 行。
def updateChunkState(chunkId: UUID, state: ChunkState, comment: Option[String], sourceLanguage: Option[String]): Either[ChunkNotFoundError, Unit] = {
val updateParams = List(Some(state), comment, sourceLanguage).flatten
val queryFiltered = ChunkTable.query.filter(_.id === chunkId.toString)
val query = (comment, sourceLanguage) match {
case (Some(_), Some(_)) => queryFiltered.map(c => (c.state, c.comment, c.sourceLanguage))
case (Some(_), _) => queryFiltered.map(c => (c.state, c.comment))
case (_, Some(_)) => queryFiltered.map(c => (c.state, c.sourceLanguage))
case _ => queryFiltered.map(c => (c.state))
}
exec(query.update(updateParams:_*)) match {
case 0 => Left(ChunkNotFoundError(chunkId))
case n if n > 0 => Right(())
}