Как Future[Seq[Option[Long]]] привести к типу Long

Я только начал работу со Scala и ни как не могу в ней разобраться.

def setReg (sid: String, reg: String) = {

// Получаю Id из БД
val userId = sidDAO.findUserIdBySid(sid).map(us => us.map(_.userId))

// Вношу изменения по полученному Id
userDAO.updateReg(userId, reg)

}

Проблема в том что userId имеет формат Future[Seq[Option[Long]]], а мне нужно передавать Long. Как мне привести к нужному типу?


Ответы (1 шт):

Автор решения: EnverOsmanov

Краткий ответ - приводить не обязательно. Можно сразу передавать.

sidDAO.findUserIdBySid(sid).map(us =>
  us.map(u => 
    u.userId.map(id =>
      userDAO.updateReg(id, reg)
    )
  )
)

Но обычно нам нужно дождаться успешного результата Future. Для этого внутренние Future нужно вытащить наружу из под слоёв Seq и Option.

a) Убрать Option из коллекции можно с помощью flatten либо flatMap.

val userIds: Seq[Long] = users.map(_.userId).flatten
val userIds: Seq[Long] = users.flatMap(_.userId)

б) Пройтись по коллекции и обработать каждую Future нам поможет Future.traverse.

val updates: Future[Seq[Unit]] = 
  Future.traverse(userIds)(userId => siDAO.updateReg(userId, reg))

в) Вложенные Future[Future[Long]] убираются так же с использованием flatten или flatMap.

Смотрим всё вместе:

sidDAO.findUserIdBySid(sid).flatMap{us =>
  val userIds = us.flatMap(_.userId)

  Future.traverse(userIds)(userId => siDAO.updateReg(userId, reg))
}

Тоже самое с использованием for синтаксиса:

for {
  us <- siDAO.findUserIdBySid(sid)

  userIds = us.flatMap(_.userId)

  _ <- Future.traverse(userIds)(userId => siDAO.updateReg(userId, reg))
} yield ()
→ Ссылка