Ken
Ken

Reputation: 179

Get Future objects from Future Options in Scala

I am new to Scala from Java so the functional programming thing is still a bit difficult for me to understand. I have a project in Play framework. I need to query the database to get rows with ids and display them in a html template.

Here is my code

 def search(query: String) = Action.async{ request =>
    val result = SearchEngine.searchResult(query)
    val docs = result.map(DocumentService.getDocumentByID(_).map(doc => doc))
    val futures = Future.sequence(docs)
    futures.map{documents =>
      Ok(views.html.results(documents.flatten))
    }
  }  

getDocumentByID returns a Future[Options[Document]] object, but my results template takes Array[Document] so I have tried to no avail to transform the Future[Options[Document]] to Array[Document]

The current code I have is the closest I have been, but it still does not compile. This is the error:

Error:(36, -1) Play 2 Compiler: 
    found   : Array[scala.concurrent.Future[Option[models.Document]]]
    required: M[scala.concurrent.Future[A]]

Upvotes: 3

Views: 679

Answers (1)

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

Try to collect only the Somes from the Future returned by the getDocumentByID

val docs = result.map { res =>
  val f: Future[Option[Document]] = DocumentService.getDocumentByID(res)
  f.collect { case Some(doc) => doc } 
}.toList

val futures = Future.seqence(docs) //notice that docs is converted to list from array in the previous line

General suggestion

Do not use Arrays. Arrays are mutable and they do not grow dynamically. So it is advisable to avoid using Array in concurrent/parallel code.

Upvotes: 3

Related Questions