Ken Ken - 18 days ago 8
Scala Question

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]]

Answer

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.

Comments