Expand description
A query to rank an index’s groups by a per-group aggregate — “top
5 restaurants by average grade” — reading grovedb’s per-axis
secondary Merk of an indexed tree (PR #657, PV14). Unlike the
count / sum / average surfaces this one never opens the value
trees: the ordering is maintained on write, so a ranked read is
O(log n + k) with a proof.
Types and module structure for the ranked (top-k / bottom-k)
document query —
SELECT <agg> GROUP BY <prop> ORDER BY <agg> DESC LIMIT n OFFSET m.
A ranked query answers “which n groups score highest (or lowest) on
an aggregate, starting from rank m?” in O(log n + k) with a proof,
by reading grovedb’s per-axis secondary Merk of an indexed tree
(grovedb PR #657). The contract opts in per index via
rankedCountable / rankedSummable / rankedAverageable (meta
schema v3 / PV14); the write path keeps the secondaries in sync. See
[crate::drive::document::ranked_index_tree_type] for the storage
layout this query reads.
The implementation is split across siblings, mirroring
[super::drive_document_count_query]:
- [
mode_detection] — request-shape validation + the versioned [mode_detection::detect_ranked_mode] that resolves(select, group_by, order_by, limit, offset)into aDocumentRankedMode. - [
index_picker] — [index_picker::find_ranked_index_for_axis], the covering-index picker for a(group_by property, axis, aggregate field)triple. - [
path] — the load-bearing prover/verifier-agreement path builder (DriveDocumentRankedQuery::indexed_property_name_tree_path). - [
execute_top_k] — the two executors onDriveDocumentRankedQuery(no-proof read, proof generation). - [
executors] — theimpl Drivewrappers the dispatcher calls. - [
drive_dispatcher] —DocumentRankedRequest/DocumentRankedResponseandcrate::drive::Drive::execute_document_ranked_request. - [
tests] (cfgserver+test) — unit + integration tests.
§What makes this query shape different
Every other aggregate query in this crate walks value trees under a
property-name tree and aggregates what it finds. A ranked query never
touches the value trees at all: the answer lives pre-sorted in the
secondary Merk, keyed by (sort_key ‖ group_key). Three consequences
shape the API:
whereclauses are equality pins on a compound prefix — or absent. A single-property ranked index has no prefix to narrow, so its requests carry nowhere. A compound ranked index[p1, …, pn]maintains one secondary per prefix value (per-prefix semantics: each terminalpnproperty-name tree, inside the[p1, …, pn-1]value trees, is its own indexed tree — grovedb creates and populates it in the same document batch), so a request must pin every leading property with an equality clause to name which prefix’s secondary the walk reads. Awhereon the grouped (terminal) property itself would ask for a filtered ranking, which no secondary can express — it is sorted by aggregate, not by group key — and is rejected rather than silently ignored, as is any non-equality prefix clause except oneIN: exactly one leading pin may carry 2..=[MAX_PREFIX_IN_BRANCHES] distinct elements (a single-elementINnormalizes to the equality pin), read as one walk per element and merged by(aggregate, encoded pin, group key), proved in a single branchedPathQueryenvelope with per-element authenticated absence. Anullpin cannot combine with anIN(null addresses its prefix through an empty path segment the branched proof cannot express), andOFFSETis rejected together withIN.limitis mandatory,offsetis depth-bounded,start_atis refused.limitis thekof the walk and the ranked surface has no server default for it, so it must be supplied.offsetis the rank the page starts at and is unbounded above: grovedb counts the skipped region from the subtree aggregates rather than walking it entry by entry, so both executors areO(log n + k)regardless of offset and a large offset is not a cost lever on either. Only the proved result additionally attests the count. So the offset needs no ceiling.start_at/start_aftername a document id, which does not appear anywhere in an aggregate-ordered keyspace.- Entry order IS the ranking order. The executor returns entries
in the order grovedb walked the secondary; callers must not
re-sort. Ties are broken by group key — see
DriveDocumentRankedQuery::descending.
Re-exports§
pub use drive_dispatcher::DocumentRankedRequest;pub use drive_dispatcher::DocumentRankedResponse;
Modules§
- drive_
dispatcher - Top-level dispatcher for the ranked
(
ORDER BY <aggregate> LIMIT n OFFSET m) request. - execute_
top_ k - The two ranked executors on
DriveDocumentRankedQuery: a direct read of the axis secondary, and generation of the equivalent proof. - executors
- Per-mode ranked executors on
impl Drive. One file per response shape — the dispatcher (super::drive_dispatcher) picks between them on the request’sproveflag. - index_
picker - Covering-index picker for the ranked query, plus the shared prefix-value encoding.
- mode_
detection - Request-shape validation for the ranked query, and the versioned
(select, group_by, order_by, limit, offset)→DocumentRankedModeresolution. - path
- The grove path a ranked read / proof / verification is issued against.
Structs§
- Document
Ranked Mode - The resolved shape of a ranked request: which axis, which direction,
how many groups, and the
(group property, aggregate field)pair the index picker needs. - Drive
Document Ranked Query - A resolved ranked query. Shared by the prover and the verifier — both
build the grove path through
DriveDocumentRankedQuery::indexed_property_name_tree_path, so the two cannot drift on which subtree the proof is about. - Prefix
Pin - One pinned leading property of the covering compound index.
- Ranked
Entry - One group in a ranked result: the group’s index key plus its aggregate.
- Ranked
Page - A page of a ranked result: the entries, plus how many ranks were actually skipped to reach them.
- Ranked
Pagination Inputs - The pagination knobs a ranked request carries, bundled so the versioned validator reads them in one place.
Enums§
- Ranked
Axis - Which per-group aggregate the groups are ranked by.
- Ranked
Entry Value - The aggregate value carried by one ranked entry. Mirrors grovedb’s
[
grovedb::operations::proof::indexed_axis::AxisEntries] variants exactly, one scalar at a time, so aVec<RankedEntry>and anAxisEntriescarry the same information with the same types.
Constants§
- MAX_
PREFIX_ IN_ BRANCHES - Hard ceiling on the element count of the (at most one)
INprefix pin — the number of prefix branches one ranked / having-range request may fan out into. - MAX_
RANKED_ LIMIT - Hard ceiling on
k(the request’sLIMIT). - RANKED_
AVG_ SCALE - The fixed-point scale grovedb’s Avg axis sorts by:
avg_fixed_point = floor(sum * RANKED_AVG_SCALE / count)with euclidean (toward -∞) division. - RANKED_
COUNT_ ORDER_ KEY - The
ORDER BYfield name that means “the group’sCOUNT(*)”.