Skip to content

Commit

Permalink
[reactivemongo] Utility for findAndModify
Browse files Browse the repository at this point in the history
  • Loading branch information
cchantep committed Oct 24, 2016
1 parent c4538ce commit b6e630f
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 5 deletions.
16 changes: 12 additions & 4 deletions reactive-mongo/src/main/scala/Akka.scala
Expand Up @@ -10,7 +10,7 @@ import com.typesafe.config.ConfigFactory
import akka.actor.{ ActorRef, ActorSystem AkkaSystem, Props } import akka.actor.{ ActorRef, ActorSystem AkkaSystem, Props }


import reactivemongo.api.commands.GetLastError import reactivemongo.api.commands.GetLastError
import reactivemongo.bson.{ BSONArray, BSONDocument, BSONString } import reactivemongo.bson.{ BSONArray, BSONDocument, BSONString, BSONValue }
import reactivemongo.core.actors.{ import reactivemongo.core.actors.{
Close, Close,
CheckedWriteRequestExpectingResponse CheckedWriteRequestExResp, CheckedWriteRequestExpectingResponse CheckedWriteRequestExResp,
Expand Down Expand Up @@ -128,9 +128,17 @@ private[reactivemongo] class Actor(handler: ConnectionHandler)
case Request(coln, SimpleBody(ps)) { case Request(coln, SimpleBody(ps)) {
val qreq = new Request { val qreq = new Request {
val collection = coln val collection = coln
val body = ps.collectFirst {
case ("$query", q @ BSONDocument(_)) q val body = ps.foldLeft(Option.empty[BSONDocument] (
}.fold(req.body)(List(_)) List.empty[(String, BSONValue)]
)) {
case ((_, opts), ("$query", q @ BSONDocument(_)))
Some(q) opts

case ((q, opts), opt) q (opts :+ opt)
} match {
case (q, opts) q.toList :+ BSONDocument(opts)
}
} }


Try(handler.queryHandler(cid, qreq)) match { Try(handler.queryHandler(cid, qreq)) match {
Expand Down
8 changes: 8 additions & 0 deletions reactive-mongo/src/main/scala/QueryResponse.scala
Expand Up @@ -33,6 +33,14 @@ object QueryResponse {
*/ */
def count(result: Int = 0) = apply(BSONDocument("ok" 1, "n" result)) def count(result: Int = 0) = apply(BSONDocument("ok" 1, "n" result))


/**
* Prepares a response to a successful findAndModify command.
*
* @param result FindAndModify result
*/
def findAndModify(result: BSONDocument) =
apply(BSONDocument("ok" 1, "value" result))

/** /**
* Undefined response, returned by handler no supporting * Undefined response, returned by handler no supporting
* a specific query that may be handled by others. * a specific query that may be handled by others.
Expand Down
24 changes: 24 additions & 0 deletions reactive-mongo/src/main/scala/Request.scala
Expand Up @@ -171,6 +171,30 @@ object DeleteRequest {
} }
} }


/** FindAndModify request */
object FindAndModifyRequest {
/**
* @return Collection name, query, update and then options
*/
def unapply(findAndModify: Request): Option[(String, List[(String, BSONValue)], List[(String, BSONValue)], List[(String, BSONValue)])] = findAndModify match {
case Request(_, SimpleBody(("findAndModify", BSONString(col)) :: ps)) {
var q = List.empty[(String, BSONValue)]
var u = List.empty[(String, BSONValue)]
val o = List.newBuilder[(String, BSONValue)]

ps.foreach {
case ("query", ValueDocument(query)) q = query
case ("update", ValueDocument(update)) u = update
case opt o += opt
}

Some((col, q, u, o.result()))
}

case _ None
}
}

/** /**
* Extractor of properties for a document used a BSON value * Extractor of properties for a document used a BSON value
* (when operator is used, e.g. `{ 'age': { '\$gt': 10 } }`). * (when operator is used, e.g. `{ 'age': { '\$gt': 10 } }`).
Expand Down
41 changes: 40 additions & 1 deletion reactive-mongo/src/test/scala/DriverSpec.scala
Expand Up @@ -263,7 +263,8 @@ class DriverSpec extends org.specs2.mutable.Specification
List(BSONDocument("doc" 1), BSONDocument("doc" 2.3d)) List(BSONDocument("doc" 1), BSONDocument("doc" 2.3d))
) { d ) { d
AcolyteDSL.withFlatCollection(d, "anyCol") { AcolyteDSL.withFlatCollection(d, "anyCol") {
_.find(query1.body.head).cursor[BSONDocument]().collect[List]() _.find(query1.body.head).
cursor[BSONDocument]().collect[List]()
} }
} }
} aka "query result" must beLike[List[BSONDocument]] { } aka "query result" must beLike[List[BSONDocument]] {
Expand Down Expand Up @@ -310,6 +311,44 @@ class DriverSpec extends org.specs2.mutable.Specification
}.map(_.isEmpty) aka "query result" must beTrue.await(0, timeout) }.map(_.isEmpty) aka "query result" must beTrue.await(0, timeout)
} }


"support query options" in { implicit ee: EE
withFlatDriver { implicit drv: MongoDriver
AcolyteDSL.withFlatQueryHandler({
case Request("acolyte.test3", RequestBody(
List(("filter", BSONString("valC"))) :: List(
("$orderby", ValueDocument(List(("foo", BSONInteger(1))))),
("$readPreference", ValueDocument(
List(("mode", BSONString("primary")))))
) :: Nil))
QueryResponse(BSONDocument("lorem" 1.2D))
}) { con: MongoConnection
AcolyteDSL.withFlatCollection(con, query3.collection) {
_.find(query3.body.head).sort(BSONDocument("foo" 1)).
cursor[BSONDocument]().collect[List]()
}
}
}.map(_.size) aka "query result" must beEqualTo(1).await(0, timeout)
}

"support findAndModify" in { implicit ee: EE
withFlatDriver { implicit drv: MongoDriver
AcolyteDSL.withFlatQueryHandler({
case FindAndModifyRequest("test3", List(("id", BSONInteger(1))),
List(("title", BSONString("foo"))), opts)
QueryResponse.findAndModify(BSONDocument(opts))
}) { con: MongoConnection
AcolyteDSL.withFlatCollection(con, query3.collection) {
_.findAndUpdate(
BSONDocument("id" 1),
BSONDocument("title" "foo")
).map(_.value)
}
}
} aka "query result" must beSome(BSONDocument(
"upsert" false, "new" false
)).await(0, timeout)
}

"as error when connection handler is empty" in { implicit ee: EE "as error when connection handler is empty" in { implicit ee: EE
awaitRes(withFlatDriver { implicit drv: MongoDriver awaitRes(withFlatDriver { implicit drv: MongoDriver
AcolyteDSL.withFlatCollection(AcolyteDSL.handle, query3.collection) { AcolyteDSL.withFlatCollection(AcolyteDSL.handle, query3.collection) {
Expand Down

0 comments on commit b6e630f

Please sign in to comment.