Ошибка компилятора в ответе на вложенные фьючерсы с Play и ReactiveMongo

У меня есть запись монго, где одно поле представляет собой список. Если запись не существует, я хочу добавить новую. Если он существует, я хочу добавить новый элемент в список.

В конце я хочу вернуть клиенту ОК, но только после успешного завершения операции. Не строгое требование, но, на мой взгляд, это то, что имеет смысл для пользователя.

Это то, что у меня есть сейчас - это работает, но при обновлении он перезаписывает старый список вместо добавления нового элемента.

def myMethod(value:String, value2:String) = Action {

  Async {
    val myElement = Json.obj(
      "key" -> value2
    )

    val myDBEntry = Json.obj(
      "key" -> value,
      "list" -> List(myElement)
    )

    collection.update(Json.obj("key" -> value), myDBEntry, upsert = true).map(lastError =>
      Ok("Mongo LastError: %s".format(lastError)))
  }
}

Чтобы проверить, существует ли список, и добавить элемент/создать новый список, я начал с чего-то вроде (это заменяет блок collection.update в предыдущем коде):

val futureResult:Future[Option[JsObject]] = collection.find(Json.obj("key" -> value)).one[JsObject]

futureResult.map { result =>

  if (result.isEmpty) {
      collection.insert(myDBEntry).map(lastError =>
        Ok("Mongo LastError: %s".format(lastError)))


  } else {
      //this not the correct command yet - but compiler already fails because method is not returning correct future 
      collection.update(Json.obj("key" -> value), myDBEntry, upsert = true).map(lastError =>
        Ok("Mongo LastError: %s".format(lastError)))
  }


}

Но компилятору, похоже, не нравится такая вложенность: "Несоответствие типов, ожидаемое: Будущее[Результат], фактическое: Будущее:[Будущее[ПростойРезультат[Ничего]]]"

В любом случае, я чувствую, что этот способ немного неудобен, и должен быть более элегантный способ решить эту проблему, но я новичок в Futures и ReactiveMongo и понятия не имею. Как мне это решить?

Изменить: я также нашел этот пост, но я думаю, что он возвращает ответ до завершения операции БД, и я не хочу это.


person User    schedule 13.08.2013    source источник


Ответы (1)


Попробуйте изменить эту строку:

futureResult.map { result =>

К этому:

futureResult.flatMap { result =>

Когда вы выполняете карту для будущего и внутри этого блока карты возвращаете другое будущее, вам нужно вместо этого использовать flatMap, так как это сгладит вложенность.

person cmbaxter    schedule 13.08.2013