count¶
Returns the number of records matching the criteria, without materializing any record values. Uses the same criteria shape as find.
Shape¶
Response¶
Cost¶
- Single-criterion indexed path — uses
idx_count_cb, the inline index-walk counter. Zero record fetches — O(1) per B+ tree hit. Fastest path. neqalgebraic shortcut —count(neq X)rewrites tocount(*) - count(eq X): two cheap counts instead of a near-everything scan. Same trick applies insideaggregate.- AND of indexed leaves —
PRIMARY_INTERSECTplanner branch (2026.05+). Each leaf's btree walks into aKeySet(xxh128 hashes, lock-free CAS inserts), sets intersect, and the count is just|result|— no per-record fetch. Big win when the intersection is small. See find → AND index intersection. - Mixed AND (indexed + non-indexed) — primary index picks candidates, other criteria filter via the criteria tree (
criteria_match_tree). Still fast because Zone B is read only for candidates that survive the primary index. - Pure-OR (all children indexed) — B+ tree lookups unioned into a
KeySet; count =|KeySet|. No record fetch, no per-record match. - Full scan — parallel per-shard Zone A walk. 2–3 ms on 1 M records.
See find → OR criteria for the full planner table.
count is always cheaper than find + ignoring results because it skips payload materialization and serialization.
Empty criteria¶
Returns the total active record count (same as size without the orphan field). Uses the cached metadata/counts value — O(1).
Examples¶
Count by status¶
// Request
{"mode":"count","dir":"acme","object":"orders",
"criteria":[{"field":"status","op":"eq","value":"paid"}]}
// Response
{"count": 8432}
Range count¶
{"mode":"count","dir":"default","object":"events",
"criteria":[
{"field":"severity","op":"gte","value":"3"},
{"field":"created","op":"gte","value":"20260418000000"}
]}
CLI shortcut¶
Omit the criteria argument to get the O(1) metadata count. Criteria must be a JSON array in a single shell-quoted argument:
When to prefer aggregate¶
If you want multiple counts (by status, by region, etc.) in one trip, use aggregate with group_by instead of N round trips.