Permalink
Browse files

[reactivemongo] Utility for findAndModify

  • Loading branch information...
cchantep
cchantep committed Oct 24, 2016
1 parent c4538ce commit b6e630fab550af1e4174ff035c7aa63d9236131d
@@ -10,7 +10,7 @@ import com.typesafe.config.ConfigFactory
import akka.actor.{ ActorRef, ActorSystem AkkaSystem, Props }
import reactivemongo.api.commands.GetLastError
import reactivemongo.bson.{ BSONArray, BSONDocument, BSONString }
import reactivemongo.bson.{ BSONArray, BSONDocument, BSONString, BSONValue }
import reactivemongo.core.actors.{
Close,
CheckedWriteRequestExpectingResponse CheckedWriteRequestExResp,
@@ -128,9 +128,17 @@ private[reactivemongo] class Actor(handler: ConnectionHandler)
case Request(coln, SimpleBody(ps)) {
val qreq = new Request {
val collection = coln
val body = ps.collectFirst {
case ("$query", q @ BSONDocument(_)) q
}.fold(req.body)(List(_))
val body = ps.foldLeft(Option.empty[BSONDocument] (
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 {
@@ -33,6 +33,14 @@ object QueryResponse {
*/
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
* a specific query that may be handled by others.
@@ -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
* (when operator is used, e.g. `{ 'age': { '\$gt': 10 } }`).
@@ -263,7 +263,8 @@ class DriverSpec extends org.specs2.mutable.Specification
List(BSONDocument("doc" 1), BSONDocument("doc" 2.3d))
) { d
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]] {
@@ -310,6 +311,44 @@ class DriverSpec extends org.specs2.mutable.Specification
}.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
awaitRes(withFlatDriver { implicit drv: MongoDriver
AcolyteDSL.withFlatCollection(AcolyteDSL.handle, query3.collection) {

0 comments on commit b6e630f

Please sign in to comment.