Repository navigation
v4.0.0
mongo4s 4.0.0
Pipeline updates, sessions without a transaction, $geoNear and three more stages, and a testkit fake that answers
the way the server does. Most breaks are compile errors; a few calls now refuse what they used to accept quietly.
Full migration guide: COMPATIBILITY.md.
libraryDependencies += "org.mongo4s" %% "mongo4s-core" % "4.0.0"Breaking changes
- An
Updatethat changes one path twice is refused when it renders —inc(n, 1).and(inc(n, 2))used to send
{"$inc": {"n": 2}}and lose the first change. Paths that overlap across operators are refused too; the server
refused those anyway. No compile error behind this one. findPagereturnsKeysetPage(items, next)— passnextasafter; it isNoneon the last page.watchAttemptingyieldsChangeEvent[DecodeResult[A]], so an event whose document fails to decode still
arrives, resume token included.watchAsAttemptingon the client and the database changed the same way.distinctover an array answers with its elements —distinct[C, B]throughDistinctOf. A call that named
the type argument names both now, or neither.regex,mod,hasSizeandpopFirst/popLastcompile only on text, numeric and collection fields.- A
limitorbatchSizebelow one and a negativeskipthrow where they are set —FindQuery,
CountOptions,WatchOptions,StageandPage. MongoDB reads alimitof 0 as no limit at all. ChangeEventgainednamespaceanddestination— positional construction takes two more arguments.Updatehas aPipelinecase,Stagefour new cases,MongoCollectionthree new members — an exhaustive
match or an implementation of your own has more to cover.- The testkit fake takes the runtime's
RsBridgeinstead of anemitfunction —
FakeMongoCollection[IO, S, User](codec)— and itslistIndexesdescribes indexes as the server does. WireCodec.spellsAsremoved.
New features
- Pipeline updates —
Update.pipeline(stages*)over$addFields,$project,$unsetand$replaceRoot,
taken byupdateOne,updateMany,findOneAndUpdateand bulk updates. $geoNearwithGeoNearOptions— query, distance bounds, multiplier,includeLocs.$unset,
$sortByCountand$bucketAuto;bucketAutoRoundedcompiles only on a numeric field, the only kind the
server rounds.createIndexes,dropIndexes,renameCollection.MongoClient.withSessionandSessionOptions— a causally consistent or snapshot session without a
transaction, given to every call in the body.- The
findOneAnd*options carrycollation,hint,maxTime,commentandbypassDocumentValidation. findPage(descending = true),Index.expiringAtFieldTime,BaseMongoRepository.createDirect,
BulkWriteFailed.result,Effect.sleep.
Bug fixes
Each reproduced by a failing test first; the fake-versus-server ones are pinned by parity specs against MongoDB 8.2.
- A sum type's codec, and one mapped with
imap/iemap, reported the wrong naming — on a direct collection a
snake_caseenum entity got camelCase filters and updates that matched nothing. emap/iemapover anOptioncodec could not read back the empty value it wrote.- A commit that ran out of
maxCommitTimewas retried until the retry window closed. Whole-transaction retries
now back off with jitter, as the driver specification requires. - A transaction body that threw while being built left the transaction open, and the default
bracketCase—
kyo's and rapid's — released nothing in the same case. - A repository write failing in a later batch named the command by its position in that batch, and its result
left out the batches before it. - Cancelling a
unitcall left its subscription running on cats-effect and kyo. - zio and rapid asked a cursor for a whole buffer to answer
oneoroption. Repository.findOneAndUpdatereplaced your projection; a sub-millisecondmaxTimemeant no limit;Either's codec
let a_typefield overwrite the discriminator;BsonDecoder[BigDecimal]threw on a non-finiteDouble;
Repository.existscounted every match;selectAsrecomputed names and decoders for every document.- The fake answers like the server in many more places — duplicates in
insertManyand unordered bulks, unique
indexes enforced and named as the server names them, streams read when they run, collations refused, numbers
compared across widths, replacements keep their_id, no-op updates not counted as modified, and index creation
and drops failing where the server fails.
Benchmarks
A/B against 3.0.0 on one machine, all six harnesses: no measurable change. Allocations per operation are identical
and every difference sits inside run-to-run error; the driver bump to 5.12.0 is not slower.
BENCHMARKS.md keeps the 3.0.0 measurements, which
stand.
Compatibility
Scala 3.9 LTS; building requiresJDK 25.mongo4s-kyoremains outside the binary compatibility promise while
kyo is on a release candidate.- MongoDB Java driver
5.12.0. Tested against JDK 25 and MongoDB 8.2. - Not binary compatible with
3.x— see the migration guide.