Show
We'll create 300 documents with a running index i (0..299).
We will do a findAndModify 300 times at once, querying for i != 0 and updating i = 0
We'll see that a huge amount of findAndModify s fail.
Steps:
Run a MongoDB instance (3.2.16) on localhost:27017
Install the latest sbt
Type sbt in the shell and the interactive sbt will start.
sbt:mongobug>
sbt:mongobug> set libraryDependencies += "org.reactivemongo" %% "reactivemongo" % "0.12.6"
sbt:mongobug> set libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.25"
sbt:mongobug> console
scala>
scala> :paste
// Entering paste mode (ctrl-D to finish)
import com.typesafe.config.ConfigFactory
import reactivemongo.api._
import reactivemongo.api.collections.bson.BSONCollection
import reactivemongo.bson._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits._
import scala.concurrent.duration.Duration
val driver = new MongoDriver(Some(ConfigFactory.empty()), None)
val conn = driver.connection(Seq("localhost:27017"))
val db = Await.result(conn.database("test"), Duration.Inf)
val col = db.collection[BSONCollection]("col")
Await.ready(col.remove(document()), Duration.Inf)
for (i <- 1 to 300) Await.ready(col.insert(document("i" -> i)), Duration.Inf)
val results = for (_ <- 1 to 300) yield {
col.findAndUpdate(
document("i" -> document("$ne" -> 0)),
document("$set" -> document("i" -> 0)),
sort = Some(document("i" -> 1))
)
}
results.map(_.map(println))
// Exiting paste mode, now interpreting.
After the application is ran, the output will look something like this:
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
FindAndModifyResult(Some(UpdateLastError(true,None,1,None)),Some(BSONDocument(<non-empty>)))
FindAndModifyResult(Some(UpdateLastError(true,None,1,None)),Some(BSONDocument(<non-empty>)))
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
...
...
Every line that looks like this:
FindAndModifyResult(Some(UpdateLastError(false,None,0,None)),None)
means a failure in updating.
When we remove the sorting, all the updates will succeed.