Queries are plain JavaScript objects whose keys are field names and whose values
are either a direct value (implicit $eq) or an operator object.
collection.find({ role: "admin" })
// equivalent to { role: { $eq: "admin" } }Matches documents where field === value. Strict equality; no type coercion.
collection.find({ age: { $eq: 30 } })Matches documents where the field value is strictly greater than / less than the given value.
collection.find({ age: { $gt: 18 } })
collection.find({ score: { $lt: 100 } })
collection.find({ age: { $gt: 18, $lt: 65 } })Only numeric comparisons are meaningful. Non-numeric fields are not indexed by
NumberIndex and will not match.
Matches documents where the field value equals any of the listed values.
collection.find({ role: { $in: ["admin", "editor"] } })Matches documents where the field is present (true) or absent (false).
collection.find({ email: { $exists: true } })
collection.find({ deletedAt: { $exists: false } })$exists is always evaluated in the residual pass; no index supports it.
Combines multiple sub-queries with logical AND. The result matches documents that satisfy every sub-query.
collection.find({
$and: [
{ role: "admin" },
{ age: { $gt: 18 } }
]
})Top-level fields in the same query object are already implicitly ANDed, so
$and is only needed when multiple conditions target the same field or when
explicit grouping is required.
Unsupported operators (e.g. $or, $not, $nor) throw at query compilation
time.
compileQuery(query) converts the raw query object into a tree of
CompiledQuery nodes:
CompiledQuery = AndPredicate | FieldPredicate
AndPredicate = { type: "and"; predicates: CompiledQuery[] }
FieldPredicate = { type: "field"; field: string; operators: FieldOperator[] }
The compiled form is passed to the query planner and to the per-document
evaluator. Compilation happens once per find() or findOne() call; cursor
iteration uses the already-compiled query.
collection.find(query) compiles the query, asks the index manager to plan a
candidate set, and returns a PocketCursor. The cursor captures a
snapshot of { id, offset } pairs at creation time.
Subsequent writes — inserts, updates, deletes — are invisible to the cursor. This is an intentional invariant: cursor iteration is deterministic and unaffected by concurrent mutations within the same process.
Each call to cursor.next():
- Picks the next candidate from the snapshot.
- Reads the document from disk at the stored file offset.
- Evaluates the full compiled query against the document.
- Returns the document if it matches, or advances to the next candidate.
cursor.toArray() drains the cursor and collects all matching documents.
Stops iteration after returning count matching documents. Must be a
non-negative integer. A limit of 0 returns no documents.
Skips the first count matching documents before returning results. Must be a
non-negative integer. Skipping is applied after query evaluation, not before
disk reads.
Updates are expressed as an object whose keys are operator names. Unsupported operators throw immediately.
Sets the listed fields to the given values. Adds the field if it does not exist.
collection.updateOne(id, { $set: { name: "Grace", role: "admin" } })Removes the listed fields from the document. The value in the $unset object
is ignored; by convention use 1 or true.
collection.updateOne(id, { $unset: { tempFlag: 1 } })Increments a numeric field by the given amount. Throws if the field does not exist or is not a number.
collection.updateOne(id, { $inc: { counter: 1, score: -5 } })Sets the field to the given value only if the given value is less than the current value. Throws if the field does not exist or is not a number.
collection.updateOne(id, { $min: { temperature: -10 } })Sets the field to the given value only if the given value is greater than the current value. Throws if the field does not exist or is not a number.
collection.updateOne(id, { $max: { highScore: 9000 } })Appends a value to an existing array field. Throws if the field does not exist or is not an array.
collection.updateOne(id, { $push: { tags: "typescript" } })The _id field cannot be modified by any update operator. Using $set or
$unset on _id throws before any disk write occurs.
collection.updateOne(id, { $set: { _id: "other" } }) // throws
collection.updateOne(id, { $unset: { _id: 1 } }) // throws_id can be supplied explicitly on insert if it conforms to the 24-character
lowercase hex format. Once set, it is stored inside the document JSON and
returned with every read.
Updates are always full-document rewrites. updateOne reads the current
document, applies the update expression in memory, and appends a new put1
record for the modified document. The previous put1 record for that document
id becomes a dead record and is reclaimed by the next compaction.
There is no partial-field encoding or delta log. Every put1 record contains
the complete document.