Slick left outer join fetching whole joined row as option

后端 未结 3 1865
伪装坚强ぢ
伪装坚强ぢ 2021-02-03 10:48

My join looks like this:

def byIdWithImage = for {
    userId <- Parameters[Long]
    (user, image) <- Users leftJoin RemoteImages on (_.imageId === _.id)          


        
相关标签:
3条回答
  • 2021-02-03 11:15

    I integrated helpers for this in my play-slick example app, which allow you to just call image.?

    See the .? calls, the definition of ? and the definition of mapOption.

    0 讨论(0)
  • 2021-02-03 11:25

    With the code below you can put it like: yield (user, image.maybe)

    case class RemoteImage(id: Long, url: URL)
    
    class RemoteImages extends Table[RemoteImage]("RemoteImage") {
        def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
        def url = column[URL]("url", O.NotNull)
        def * = id.? ~ url <> (RemoteImage.apply _, RemoteImage.unapply _)
    
        def maybe = id.? ~ url.? <> (applyMaybe,unapplyBlank)
    
        val unapplyBlank = (c:Option[RemoteImage])=>None        
    
        val applyMaybe = (t: (Option[Long],Option[URL])) => t match {
            case (Some(id),Some(url)) => Some(RemoteImage(Some(id),url))
            case _ => None
        } 
    }
    
    0 讨论(0)
  • 2021-02-03 11:30

    Off the top of my head, I'd use a custom mapped projection. Something like this:

    case class RemoteImage(id: Long, url: URL)
    
    def byIdWithImage = for {
        userId <- Parameters[Long]
        (user, image) <- Users leftJoin RemoteImages on (_.imageId === _.id) if user.id === userId
    } yield (user, maybeRemoteImage(image.id.? ~ image.url.?))
    
    def maybeRemoteImage(p: Projection2[Option[Long], Option[URL]]) = p <> ( 
      for { id <- _: Option[Long]; url <- _: Option[URL] } yield RemoteImage(id, url),
      (_: Option[RemoteImage]) map (i => (Some(i id), Some(i url)))
    )
    

    Using scalaz (and its ApplicativeBuilder) should help reduce some of that boilerplate.

    0 讨论(0)
提交回复
热议问题