docs: TTL limits and error codes in the README

The TTL feature commit documented what the option does but left the
limits sections stale. v1 limits now names the sweep cost (a full walk of
every TTL index entry, under the write lock for the whole pass), so the
interval reads as the tuning knob it is; "Not (yet) implemented" gains
collMod, with the consequence — drop and re-create to change an expiry.

The TTL bullet trades its collMod sentence for the two codes a user
actually hits (IndexOptionsConflict 85 on a changed expiry,
InvalidIndexSpecificationOption 197 on {_id: 1}), the features bullet
mentions the sweeper, and quick start shows a createIndex with
expireAfterSeconds so the feature is visible without reading down.
This commit is contained in:
2026-08-02 14:39:26 +03:00
parent 3c1ab6f656
commit dc92064b95

View File

@@ -19,6 +19,7 @@ mongosh --port 27017
> db.users.find({age: {$gt: 25}}).toArray()
> db.users.updateOne({name: "alice"}, {$set: {vip: true}})
> db.users.deleteOne({name: "bob"})
> db.sessions.createIndex({expireAt: 1}, {expireAfterSeconds: 3600})
```
## Features
@@ -41,8 +42,9 @@ mongosh --port 27017
- **Secondary indexes**: `createIndex`/`listIndexes`/`dropIndex` via the
three driver commands, single-field and compound, with `unique`,
`sparse` and `expireAfterSeconds` (TTL) options, persisted in the log
and rebuilt on open (compaction
re-emits them). The query planner turns equality / `$in` / range
and rebuilt on open (compaction re-emits them). A background sweeper
expires TTL-indexed documents through the ordinary logged write path.
The query planner turns equality / `$in` / range
predicates into index lookups across `find`, `count`, `update`,
`delete`, `findAndModify`, and a leading `$match` in `aggregate`; every
candidate is re-checked against the full filter, so an index that
@@ -101,9 +103,10 @@ the query planner to narrow scans.
`expireAfterSeconds` must be a whole number in `[0, 2147483647]` (`0`
means "expire at the stored instant"), a non-date value at the path never
expires, an array of dates expires on its earliest member, and expiry is
coarse: a document stays visible until the next sweep. Changing the
expiry of an existing index is `IndexOptionsConflict` `collMod` is not
implemented.
coarse: a document stays visible until the next sweep. Re-creating an
index with a different expiry is `IndexOptionsConflict` (85) and an
expiry on `{_id: 1}` is `InvalidIndexSpecificationOption` (197), both as
MongoDB has them.
- **Multikey**: an array at an indexed path is indexed as a whole *and*
element-wise, mirroring the query matcher exactly, so both
`{tags: "a"}` and `{tags: ["a","b"]}` hit the index. A compound index
@@ -121,7 +124,11 @@ the query planner to narrow scans.
v1 limits: no index-accelerated sort, no hashed/text/geo/partial indexes,
and entry insert/removal is O(n) (a sorted array) — fine for a light
database, with a B-tree or id→entry map as the follow-up.
database, with a B-tree or id→entry map as the follow-up. A TTL sweep
walks every entry of every TTL index and holds the write lock for the
whole pass, so the interval is the tuning knob: expiry is never more
precise than `--ttl-sweep-secs`, and a very large TTL index wants a
longer one.
## Not (yet) implemented
@@ -129,6 +136,8 @@ database, with a B-tree or id→entry map as the follow-up.
- Real cursors (all results are returned in one batch, cursor id 0)
- Transactions, change streams, replicasets
- Compression (OP_COMPRESSED)
- `collMod`, so an index's `expireAfterSeconds` cannot be changed in
place — drop the index and re-create it with the new expiry
- `dropCollection`/`dropDatabase` write no log record, so a dropped
collection (and its index definitions) resurrect on restart; and
compaction never resets `log_bytes`, so every write after the first