Reference
Supported operations
A plain list of what the emulation implements, family by family, and where it stops. Everything here is the operator, stage, and method set the shim actually recognises. Anything absent raises MongoTestUnsupportedException rather than guessing.
This is an emulation, not MongoDB, so the interesting question is not “does it run?” but “does it answer the same way?”. Each family below is exercised by a differential lane in CI that runs the same scenario against the shim and against a real MongoDB 7.x/8.x server and diffs both observations. Real MongoDB is the reference, and a disagreement makes the shim wrong by definition. See How it works for the lane and the engines behind it.
CRUD
Implemented on MongoCollection, in both the plain and the ClientSession form unless noted:
| Operation | Notes |
|---|---|
| insertOne, insertMany | Generated _id is written back into the caller's document instance, as the driver does. ordered=false fails fast. |
| find | Cursor options: filter, sort, projection, skip, limit, collation. Other FindIterable options fail fast. |
| replaceOne, updateOne, updateMany | Includes upsert. Aggregation-pipeline updates fail fast. |
| deleteOne, deleteMany | Filter only; the option bag fails fast. |
| findOneAndUpdate, findOneAndReplace, findOneAndDelete | Plain and ClientSession forms, with and without options. In a transaction, the returned pre/post-image and the staged write both use the session view. |
| bulkWrite | InsertOneModel, ReplaceOneModel, UpdateOneModel, UpdateManyModel, DeleteOneModel, DeleteManyModel. Plain and ClientSession forms are supported; transactional models stage in order. Any other model fails fast, and so does a pipeline update inside one. |
| countDocuments, estimatedDocumentCount | estimatedDocumentCount() is the no-argument form only. |
| distinct | Plain and ClientSession forms, with and without a filter. In a transaction, values come from the session overlay and reflect staged inserts, updates, and deletes; after commit or abort, the session form follows the ordinary committed view. |
| aggregate | Plain and ClientSession forms. A transaction's source and $lookup collections both read through its overlay. allowDiskUse and batchSize are accepted no-ops; the other AggregateIterable options fail fast. |
| createIndex, listIndexes, drop | See Indexes. dropIndex, dropIndexes and createIndexes are not implemented. |
On MongoDatabase: getName, getCollection, createCollection(String), listCollectionNames, drop, and the codec-registry accessors. On MongoClient: startSession, getDatabase, listDatabaseNames, close, and the codec-registry accessors.
Query operators
Recognised in filters, at the top level and nested:
| Family | Operators |
|---|---|
| Logical | $and$or$nor$not |
| Comparison | $eq$ne$gt$gte$lt$lte$in$ninImplicit equality included. Numbers compare by value across BSON numeric types. |
| Element | $exists$type$type takes the string aliases and the numeric type codes. |
| Evaluation | $regex$options$modRegex flags i, m, s, x; $options is only valid alongside $regex. |
| Array | $all$size$elemMatchDotted paths and array-index paths are supported. An $elemMatch nested directly inside another $elemMatch fails fast. |
Update operators
| Family | Operators |
|---|---|
| Field | $set$unset$inc$mul$min$max$rename$setOnInsert$currentDate$currentDate accepts true and {$type: "date"}; the timestamp type fails fast. |
| Array | $push$addToSet$pull$pullAll$pop$push modifiers: $each, $position, $sort, $slice. $addToSet takes $each. $pull conditions are limited to the comparison operators $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin. |
| Positional | $$[]$[<identifier>]arrayFilters drives the filtered form, including dotted-field conditions, and enforces the server's unknown/unused/duplicate-identifier errors. |
Upserts are supported, built from the filter-derived seed document. Any update operator outside the list above fails fast by name.
Aggregation
Stages:
| Stage | Notes |
|---|---|
$match | Reuses the filter translator, so a leading match still hits indexes. |
$project, $addFields, $set, $unset | Inclusion and exclusion rules, dotted and nested forms, computed fields. |
$sort, $skip, $limit, $count | A {$meta: "textScore"} sort key fails fast. Sorting follows the server's key rules: a missing key ties with null, and an array key stands in for its minimum element ascending / maximum element descending. |
$unwind | Shorthand and document form, including preserveNullAndEmptyArrays and includeArrayIndex. |
$group, $sortByCount | Output order is first-appearance, which is deterministic where the server leaves it undefined. |
$replaceRoot, $replaceWith | Supported. |
$lookup | Equality form only: from, localField, foreignField, as. The pipeline/let form fails fast. |
Expression and accumulator operators inside those stages:
| Family | Operators |
|---|---|
| Arithmetic | $add$subtract$multiply$divideDate arithmetic follows the server: $add shifts a date by milliseconds (one date operand at most), $subtract of two dates yields the millisecond difference, and division by zero raises the server's error. |
| String | $concat$toUpper$toLower$toUpper/$toLower treat null and missing as the empty string and coerce integral numbers, as the server does; the server's remaining coercions (double, decimal, date) fail fast rather than risking a different rendering. |
| Conditional | $cond$ifNull$cond takes both the three-element array and the {if, then, else} form. |
| Array | $size |
| Date | $year$month$dayOfMonthEvaluated at UTC. The timezone option fails fast rather than being ignored. |
| Literal | $literal |
| Variables | $$ROOT$$CURRENTAny other variable reference fails fast. |
| Accumulators | $sum$avg$min$max$first$last$push$addToSet |
The engine runs pipelines as Java stages over materialised documents: correctness first, over data that fits in memory. Any stage, expression or accumulator outside these lists fails fast by name.
Indexes
| Feature | Notes |
|---|---|
| Single-field and compound | Compound indexes match on the same field list, in order. |
| unique | Duplicate keys raise the server's duplicate-key error on insert, update and upsert. Non-unique is the default. |
| Index names | Custom names, and the auto-generated field_direction form. |
| Sort direction | Recorded and reported by listIndexes(), but not enforced: the underlying store's indexes are directionless. A direction of 0 is an error, as on the server. |
| The implicit _id_ index | Reported by listIndexes() without a unique field, matching the server. |
Not implemented, each failing fast by name: TTL (expireAfterSeconds), sparse, partialFilterExpression, wildcard ($** and wildcardProjection), text (weights), index collation, storageEngine, hidden, and the key types hashed, 2d, 2dsphere and geoHaystack. Atlas search indexes fail fast separately.
Transactions and sessions
The full driver session API is implemented: startSession() with or without ClientSessionOptions, startTransaction() with or without TransactionOptions, commitTransaction(), abortTransaction(), close() (which aborts an active transaction), hasActiveTransaction(), and withTransaction(...) honouring the driver's 120-second retry budget. retrying on TransientTransactionError and re-committing on UnknownTransactionCommitResult. Atomicity holds across multiple collections and multiple databases.
Two things differ from a server, and both are stated rather than papered over. Isolation is read-your-own-writes over current committed state, not snapshot isolation: a concurrent commit can become visible to a later read inside an open transaction. The compensating guarantee is that every document read or written has its revision recorded, so a transaction that read a value someone else moved fails to commit with a TransientTransactionError rather than committing on top of it. Read concern, write concern and read preference select no behaviour in a single-process store, but their collection, database and client-level accessors are supported: withWriteConcern, withReadConcern and withReadPreference construct immutable views carrying the requested value, and the matching getters return it. Three write concerns fail fast at named boundaries: w:0 (driver.writeConcernUnacknowledged), numeric w >= 2 (driver.writeConcernMultiNode), and non-majority string or tag modes (driver.writeConcernTag). Snapshot sessions, setTransactionContext, and a ClientSession created by a different client are all refused.
The Transactions page covers every abort path and the retry contract in full.
Collation
Collation applies to sorting in find(...) and nothing else. The accepted shape is a resolvable locale with strength PRIMARY or SECONDARY; setting caseLevel, caseFirst, numericOrdering, alternate, maxVariable, normalization or backwards fails fast.
Collation-aware matching is refused explicitly: a collation set together with a non-empty filter fails fast, so a collation never silently fails to affect $eq, $in or range comparisons. Index collation, aggregation collation, distinct collation, and the collation option on count, delete, update, replace and findOneAnd* all fail fast by name. With no collation, strings order by simple binary comparison.
What fails fast
Every boundary raises MongoTestUnsupportedException (a com.mongodb.MongoException) naming the feature and a stable key, so a test can assert on the boundary rather than on message text. The named families:
| Area | Refused |
|---|---|
| Query | $where$expr$jsonSchema$text$slice$comment$sampleRate$bitsAllSet$bitsAnySet$bitsAllClear$bitsAnyClear$near$nearSphere$geoWithin$geoIntersects$geoNearPlus nested $elemMatch, unsupported projection operators, projection exclusion forms the shim cannot express, and unsupported sort specifications. |
| Writes | Aggregation-pipeline updates; the collation, hint, let and sort options on updates; collation, hint and let on deletes; collation, hint and maxTime on counts; comment and ordered=false on inserts; unsupported bulkWrite models. |
| Aggregation | Any stage outside the supported set, such as $out, $merge, $facet, $bucket, $graphLookup, $setWindowFields or $search, among others, is the $lookup pipeline form, unsupported expressions, accumulators and variables, the expression timezone option, and aggregation collation. A stage name MongoDB itself does not define gets the server's own Location40324 “Unrecognized pipeline stage name” error, so a typo fails here exactly as it would in production. |
| Indexes | TTL, sparse, partial, wildcard, text, collation, storage engine, hidden, hashed and geospatial index types, and Atlas search indexes. |
| Driver surface | watch (change streams), mapReduce, renameCollection, runCommand, createView, listCollections, listDatabases, database-level aggregate, client-level bulkWrite, index dropping, the read/write-concern and read-preference accessors, and every other driver method the shim does not implement. |
| Values and sessions | A value no codec in the effective registry can encode is the case a real driver refuses client-side too. This includes MinKey, MaxKey, and BSON undefined, which have codecs but no representation the store can hold. Documents containing the reserved field or dotted field names, snapshot sessions, setTransactionContext, and a foreign ClientSession.Types are not on a whitelist. Anything the collection's codec registry can encode is stored as that codec writes it. For example, BigDecimal becomes Decimal128, your own Codec's type however you defined it. See the compatibility matrix. |