2017-06-22 59 views
0

我很困惑如何使用只有期貨根據以前的查詢有條件地更新文檔。ReactiveMongo有條件更新

讓我說只有當該數組的大小小於給定的整數時,我纔會將某個值推送到文檔中的數組中。

我正在使用這個函數來獲取文檔,在獲取文檔後,我正在推動值 - 我無法做的是有條件地做到這一點。

def joinGroup(actionRequest: GroupRequests.GroupActionRequest): Future[GroupResponse.GroupActionCompleted] = { 
//groupisNotFull() is a boolean future 
groupIsNotFull(actionRequest.groupId).map(
    shouldUpdate => { 
    if(shouldUpdate){ 
     Logger.info(actionRequest.initiator + " Joining Group: " + actionRequest.groupId) 
     val selector = BSONDocument("group.groupid" -> BSONDocument("$eq" -> actionRequest.groupId)) 
     val modifier = BSONDocument("$push" -> BSONDocument("group.users" -> "test-user")) 
     val updateResult = activeGroups.flatMap(_.update(selector, modifier)) 
     .map(res => { 
      GroupActionCompleted(
      actionRequest.groupId, 
      actionRequest.initiator, 
      GroupConstants.Actions.JOIN, 
      res.ok, 
      GroupConstants.Messages.JOIN_SUCCESS 
     ) 
     }) 
     .recover { 
      case e: Throwable => GroupActionCompleted(
      actionRequest.groupId, 
      actionRequest.initiator, GroupConstants.Actions.JOIN, 
      success = false, 
      GroupConstants.Messages.JOIN_FAIL 
     ) 
     } 
     updateResult 
    } 
    else { 
     val updateResult = Future.successful(
     GroupActionCompleted(
      actionRequest.groupId, 
      actionRequest.initiator, 
      GroupConstants.Actions.JOIN, 
      success = false, 
      GroupConstants.Messages.JOIN_FAIL 
     )) 
     updateResult 
    } 
    } 
) 
} 

//returns a Future[Boolean] based on if there is room for another user. 
private def groupIsNotFull(groupid: String): Future[Boolean] = { 
findGroupByGroupId(groupid) 
    .map(group => { 
    if (group.isDefined) { 
     val fGroup = group.get 
     fGroup.group.users.size < fGroup.group.groupInformation.maxUsers 
    } else { 
     false 
    } 
    }) 

}

我爲什麼我不能做到這一點困惑。編譯錯誤是:

錯誤:類型不匹配; 發現:scala.concurrent.Future [response.group.GroupResponse.GroupActionCompleted] 要求:response.group.GroupResponse.GroupActionCompleted

兩個if和else分支 'updateResult'。

作爲一個側面的問題..這是有條件地更新文件的正確方法 - 即查詢它,做一些邏輯,然後執行另一個查詢?

+0

爲什麼不看看'findAndModify'? – cchantep

+0

@cchantep據我所知,我不能在查詢本身內進行條件更新。這是由設計閱讀MongoDB的文檔後,該業務邏輯應該走出查詢 – StackTraceYo

+0

這取決於你的條件是什麼意思的,'findAndModify'允許更新或刪除現有的文檔與查詢匹配的。 – cchantep

回答

1

確定了它 - 你需要flatMap第一Future[Boolean]這樣的:

groupIsNotFull(actionRequest.groupId).flatMap(... 

使用flatMap中,結果將是一個未來[T]與map你會得到一個未來[未來[T]]。編譯器知道你想返回一個Future [T],所以它期望映射返回一個T,並且你試圖返回一個Future [T] - 所以它會拋出錯誤。使用flatMap可以解決這個問題。

在地圖上的一些進一步的淨度VS flatmap這裏:In Scala Akka futures, what is the difference between map and flatMap?

+0

真棒謝謝,但我最終用不同的方法去更新它的條件。我在文檔中添加了一個字段,每次添加數組時都會減少該字段。然後查詢將選擇與id匹配的文檔,並且該字段的值> 0 – StackTraceYo

+0

沒問題。但是,由於您想要選擇性地返回文檔,因此返回Future [Option [Document]]可能更「有用」。即您返回一些(doc)如果有一個文檔或無,如果它的大小閾值以下。這可能是比if/else塊更好的模式。 – jsdeveloper

0

我相信這個問題是因爲joinGroup2函數的返回類型是未來[迴應],但你正在返回剛纔在別的塊的響應。如果您查看mapTo [T]函數的簽名,它將返回Future [T]。

我想你需要在未來包裝Response對象。事情是這樣的:

else { 
    Future { Response(false, ERROR_REASON) } 
} 

順便說一句,你有一個錯字:Respose - >響應

+0

'Future.successful'純價值 – cchantep

+0

結束語在未來仍然給我的錯誤: 錯誤類型不匹配; 實測值:scala.concurrent.Future [response.Response] 需要:響應。響應 我認爲這是因爲if語句中有一個嵌套的未來的第二個map函數,我對這個case如何使用flatMap有點不穩定 – StackTraceYo

+0

你試過Future.successful(Response(false,「FAILURE」 ))? – jsdeveloper