2017-06-22 16 views
0

先物のみを使用して以前のクエリに基づいて条件付きで文書を更新する方法について混乱します。ReactiveMongo条件付き更新

私は、その配列のサイズが指定されたIntegerより小さい場合にのみ、ある値をドキュメントの配列にプッシュしたいとします。

ドキュメントを取得した後、この関数を使用してドキュメントを取得しています。値をプッシュしていますが、私が行うことができないのは条件付きで行うことです。私はこれを行うことができない理由で混乱しています

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] 必要は:両方の場合、他の枝 'updateResult' の

をresponse.group.GroupResponse.GroupActionCompleted。

これは、条件付きでドキュメントを更新する適切な方法です。つまり、それをクエリしていて、ロジックを実行してから別のクエリを実行しますか?

+0

なぜ 'findAndModify'を見ていませんか? – cchantep

+0

@cchantep私が理解しているように、私はクエリ自体の中で条件付きの更新を行うことはできません。これはmongodbのドキュメントを読んだ後に設計されたもので、ビジネスロジックがクエリから外れるべきであることを意味します。 – StackTraceYo

+0

条件付きで意味することは「findAndModify」によってクエリに一致する既存のドキュメントを更新または削除できます。 – cchantep

答えて

1

OK]をクリックしてそれを得た - あなたはこのような最初のFuture[Boolean]flatMapする必要があります。

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

flatMap、使用結果はFuture [T]になります。mapとすればFuture [Future]が得られます。コンパイラは、あなたが未来[T]を返すことを知っているので、マップがTを返すことを期待し、未来[T]を返そうとしているので、エラーをスローします。 flatMapを使用するとこれが修正されます。

ここflatmap対マップ上のいくつかのさらなる透明度:In Scala Akka futures, what is the difference between map and flatMap?

+0

素晴らしいおかげで、しかし、私は条件付きでそれを更新する別の方法で行くことになった。私は配列が追加されるたびに減らされた文書上のフィールドを追加しました。そして、クエリはIDと一致するドキュメントを選択し、そのフィールドの値> 0 – StackTraceYo

+0

問題はありません。ただし、オプションでドキュメントを返す必要があるため、将来の[Option [Document]]を返すためにはもっと機能的かもしれません。つまり、ドキュメントがある場合はSome(doc)を返し、サイズのしきい値を下回る場合はNoneを返します。これはif/elseブロックよりも良いパターンかもしれません。 – jsdeveloper

0

私はこの問題は、joinGroup2関数の戻り値の型がFuture [Response]なので、まだelseブロックのResponseを返すためだと思います。 mapTo [T]関数のシグネチャを見ると、Future [T]が返されます。

今後、Responseオブジェクトをラップする必要があると思います。このような何か:

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

ところであなたはタイプミスを持っている:Resposeは - >応答

+0

純粋な値のための 'Future.successful' – cchantep

+0

それを将来的にラッピングすると、私にエラーが発生します: エラータイプの不一致。 が見つかりました:scala.concurrent.Future [response.Response] required:レスポンス。応答 ifステートメントにネストされた未来の2番目のマップ関数があるため、このケースでflatMapを使用する方法が少し不安です – StackTraceYo

+0

Future.successful(Response(false、 "FAILURE" ))? – jsdeveloper