def getCommentIds(
commentTargetId: Long,
sortOrder: CommentOrderEnum): Future[Seq[CommentStatsBO]]
def getCommentDetail(commentId: Long): Future[Option[CommentDetailDTO]]
def getCommentListWithDetail(
targetId: Long,
sortOrder: CommentOrderEnum,
page: Int): Future[Seq[CommentDetailDTO]] = {
commentModel.getCommentIds(targetId, sortOrder).flatMap {
commentStatsBOSeq =>
Future.traverse(commentStatsBOSeq) { commentStatsBO =>
// commentDetail is a Future[Option[T]]
val commentDetail = getCommentDetail(commentStatsBO.iId)
commentDetail.map(commentOpt =>
commentOpt
// merge the stat info into the comment detail
.map(_.copy(replyCount = Some(commentStatsBO.replyCount)))
.getOrElse(CommentDetailDTO))
}
}
}
case class CommentDetailDTO(
id: Long,
author: JsObject,
detail: CommentDetail,
replyCount: Option[Int] = None
)
Firstly, the function getCommentIds
returns a sequence of CommentStatsBO, then traversing it and try to get detail for every comment. Here comes the question, getCommentDetail
returns a Future which contains an option since the comment maybe not found, in this case, how to filter those ones whose option is None? I have tried getOrElse
, but don't know how to define an empty object just like Json.obj()
since case class
doesn't support.
Thanks!
CodePudding user response:
Don't try to do too many things at the same time, rather build the solution you need step by step.
If you do a simple Future.traverse
using just getCommentDetail
you will get a Future[Seq[Option[CommentDetailDTO]]]
which then you can map
and use collect
with the Seq
to remove the Option
def getCommentListWithDetail(
targetId: Long,
sortOrder: CommentOrderEnum,
page: Int
): Future[Seq[CommentDetailDTO]] =
commentModel.getCommentIds(targetId, sortOrder).flatMap { commentStatsBOSeq =>
Future.traverse(commentStatsBOSeq) { commentStatsBO =>
getCommentDetail(commentStatsBO.iId)
} map { commentOptionalDetails =>
commentOptionalDetails.collect {
case Some(commentDetail) => commentDetail
}
}
}
Or if you use cats, you can use traverseFilter
import cats.syntax.all._
def getCommentListWithDetail(
targetId: Long,
sortOrder: CommentOrderEnum,
page: Int
): Future[Seq[CommentDetailDTO]] =
commentModel.getCommentIds(targetId, sortOrder).flatMap { commentStatsBOSeq =>
commentStatsBOSeq.traverseFilter(getCommentDetail)
}