我应该如何处理play2和Scala中的过滤器和期货

时间:2013-06-04 12:30:42

标签: mongodb scala playframework playframework-2.1

我正在努力学习期货和ReactiveMongo。 在我的情况下,我有几个邀请对象,并希望过滤掉数据库中已存在的对象。我不想更新或插入已经在数据库中的那些。因此我创建了一个过滤方法:

过滤方式:

def isAllowedToReview(invite: Invite): Future[Boolean] = {
    ReviewDAO.findById(invite.recoId, invite.invitedUserId).map {
      maybeReview => {
        maybeReview match {
          case Some(review) => false
          case None => true
        }
      }
    }
  }

DAO:

def findById(rId: Long, userId: Long): Future[Option[Review]] = findOne(Json.obj("rId" -> recoId, "userId" -> userId))

def findOne(query: JsObject)(implicit reader: Reads[T]): Future[Option[T]] = {    
   collection.find(query).one[T]
}

然后致电:

val futureOptionSet: Set[Future[Option[Invite]]] = smsSet.filter(isAllowedToReview)
save the filtered set somehow...

这不起作用,因为过滤器在这种情况下需要Invite => Boolean,但我发送Invite => Future(Boolean)。你会如何过滤并保存这个?

2 个答案:

答案 0 :(得分:3)

smsSet.map(sms => isAllowedToReview(sms).map(b => sms -> b))将包含Set[Future[(Invite, Boolean)]]类型。您应该可以致电Future.sequence将其变为Future[Set[(Invite, Boolean)]]。然后,您可以收集结果.map(_.collect{ case (sms, true) => sms})

所以将所有内容整合在一起的解决方案可能如下所示:

val futures = smsSet.map(sms => isAllowedToReview(sms).map(b => sms -> b))
val future = Future.sequence(futures)
val result = future.map(_.collect{ case (sms, true) => sms})

当您看到mapsequence时,您可以重构为:

val filteredSet = Future.traverse(smsSet){ sms => 
  isAllowedToReview(sms).map(b => sms -> b)
}.map(_.collect{ case (sms, true) => sms})

请注意,您可能只想将短信保存在那里,而不是返回该集。但是我写这篇文章的方式,所有内容都将包含在Future中,你仍然可以使用其他操作。

答案 1 :(得分:1)

您可以尝试这样的事情:

val revsFut = Future.sequence(smsSet.map(invite => ReviewDAO.findById(invite.recoId, invite.invitedUserId)))    
val toSave = for(revs <- revsFut) yield {
  val flatRevs = revs.flatten
  smsSet.filter{ invite =>
    flatRevs.find(review => /*Add filter code here */).isDefined
  }
}

我在这里做的是首先通过映射在smsSet上获取与邀请匹配的评论集,逐个获取每个,然后将其排序为单Future。然后,在for-comprehension中,我展平Set的{​​{1}},然后根据Option[Review] Set中的内容过滤掉smsSet。由于我不知道你的对象模型,我不得不将flatRevs的impl留给你,但这一点应该很简单。