Slick如何对左连接查询得到的Option类型字段执行排序操作
问题原因
左连接操作返回的右表数据是Option类型,当父评论没有关联的子评论时,childComments为None,你代码中未对replyCount做空值兜底处理,因此最终计算得到的hot(即row._4)为Option[Int]类型,无法直接执行排序操作,强行调用.get还会在空值场景下抛出异常。
最优解决方法
在map阶段就将所有Option类型的业务字段转换为非Option类型,业务上无对应子评论时回复数、子评论点赞总和默认取0即可,从根源避免Option排序的问题:
val query = Tbcomments .joinLeft(getChildCommentStatQuery) .on(_.iid == _._1) .filter { case (comments, _) => comments.itargetid === commentTargetId && comments.iparentid === 0 && comments.istatus === statusNormal } .map { case (comments, childComments) => // 无子评论时回复数默认为0,转成非Option类型 val replyCount = childComments.map(_._2).getOrElse(0) // 修正原有写法的小问题:childComments本身是Option,先flatMap再取默认值更稳妥 val childLikeSum = childComments.flatMap(_._3).getOrElse(0) val likeCountSum = comments.ilikecount + childLikeSum // 现在hot是普通Int类型,不再是Option val hot = replyCount + likeCountSum val support = comments.ilikecount - comments.inotlikecount (comments.iid, replyCount, likeCountSum, hot, support, comments.dtcreated) } .sortBy(row => sortOrder match { case LATEST_COMMENT_ORDER => row._6.desc case EARLIEST_COMMENT_ORDER => row._6.asc case SUPPORT_COMMENT_ORDER => row._5.desc case HEAT_COMMENT_ORDER => row._4.desc })
备选方案(保留Option字段的场景)
如果你有特殊业务需要保留hot为Option类型,可以在排序时指定空值的排序规则:
// 空值热度按0计算排在末尾 case HEAT_COMMENT_ORDER => row._4.getOrElse(0).desc // 或者用Slick原生的空值排序语法,None值统一放在最前/最后 case HEAT_COMMENT_ORDER => row._4.desc.nullsLast
内容的提问来源于stack exchange,提问作者BugSource
相关产品推荐
相关产品推荐

