You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The v14 ranked machinery groups at exactly one level: the deepest prefix property of an index, ranked by direct member count. Ranking one level higher — groups by their whole-subtree totals — is not expressible, and it blocks two natural features on the indexOnly-likes shape this repo itself ships as its reference fixture (yappr-likes-contract.json):
Trending hashtags: like [hashtag, postId] → $ownerId (rankedCountable) serves top posts within a pinned hashtag, but "top hashtags by total likes" would need groupBy: hashtag — a prefix level.
Creator leaderboard: like [postAuthor, postId] → $ownerId serves an author's top posts, but "top authors by likes received" needs the postAuthor level.
Shortening the index is not a workaround: on an indexOnly type, [hashtag] → $ownerId makes (hashtag, liker) the entry itself, so structural uniqueness limits each identity to one like per hashtag ever (and [postAuthor] → $ownerId to one like per author — we reproduced the 40105 on devnet). The prefix-pinned count query (count WHERE hashtag == X on the two-property index) is also refused by the exact-index-match rule, so the totals can't even be read individually.
The data already exists; so does the structure
With countable on the index, the prefix level is a CountTree: every hashtag's (or author's) whole-subtree like total is already maintained on chain — it just has no by-count ordering, so top-K over it would be O(n). GroveDB already has the right primitive: CountIndexedTree (cidx), the same order-statistic tree that backs today's group-level ranking, benchmarked in-repo (grovedb/benches/cidx_benchmark.rs: "Top-k by count: O(log n + k) for cidx vs O(n) for plain CountTree").
So the request is not a new data structure — it is wiring the existing cidx one level higher.
Proposed design
Grammar: allow the ranked axis to name the level it aggregates at, e.g. "rankedCountable": { "at": "hashtag" } on [hashtag, postId] (default: today's behavior). Same shape could later generalize to rankedSummable.
Storage/maintenance: a cidx at the declared prefix level, keyed by each group's subtree count. The count deltas already propagate through the CountTree hierarchy on every insert/delete; the new work is re-keying the affected group's cidx entry per delta — the same O(log n) pattern (bench: (k+1)·O(log n) write amplification) as existing ranked maintenance. Composes with preallocated (drained groups stay rankable at 0).
Backfill / retrofit: because the CountTree at that level already stores every group's total, the cidx can plausibly be constructed from existing state at activation — allowing the flag to be enabled on an already-registered contract rather than forcing a re-registration. Confirming whether this is feasible would be valuable independent of the rest.
Smaller independent sibling
Relaxing the exact-index-match rule to allow prefix-pinned count queries (count WHERE hashtag == X on [hashtag, postId]) would expose the already-maintained totals as point lookups (e.g. a "likes received" profile stat) even before ranking ships.
Context
Verified against a live 4.2.0-dev.5 devnet with an indexOnly likes contract modeled on the pinned fixture: group-level ranking, structural uniqueness, and the prefix-count refusal all behave as described (exact error/behavior notes available on request). This is the last structural gap for like-derived discovery surfaces on the indexOnly shape — everything else (counts, membership with absence proofs, group-level top-K, delete-by-values) works end to end.
Problem
The v14 ranked machinery groups at exactly one level: the deepest prefix property of an index, ranked by direct member count. Ranking one level higher — groups by their whole-subtree totals — is not expressible, and it blocks two natural features on the indexOnly-likes shape this repo itself ships as its reference fixture (
yappr-likes-contract.json):like [hashtag, postId] → $ownerId(rankedCountable) serves top posts within a pinned hashtag, but "top hashtags by total likes" would needgroupBy: hashtag— a prefix level.like [postAuthor, postId] → $ownerIdserves an author's top posts, but "top authors by likes received" needs thepostAuthorlevel.Shortening the index is not a workaround: on an indexOnly type,
[hashtag] → $ownerIdmakes (hashtag, liker) the entry itself, so structural uniqueness limits each identity to one like per hashtag ever (and[postAuthor] → $ownerIdto one like per author — we reproduced the 40105 on devnet). The prefix-pinned count query (count WHERE hashtag == Xon the two-property index) is also refused by the exact-index-match rule, so the totals can't even be read individually.The data already exists; so does the structure
With
countableon the index, the prefix level is a CountTree: every hashtag's (or author's) whole-subtree like total is already maintained on chain — it just has no by-count ordering, so top-K over it would be O(n). GroveDB already has the right primitive: CountIndexedTree (cidx), the same order-statistic tree that backs today's group-level ranking, benchmarked in-repo (grovedb/benches/cidx_benchmark.rs: "Top-k by count: O(log n + k) for cidx vs O(n) for plain CountTree").So the request is not a new data structure — it is wiring the existing cidx one level higher.
Proposed design
"rankedCountable": { "at": "hashtag" }on[hashtag, postId](default: today's behavior). Same shape could later generalize torankedSummable.(k+1)·O(log n)write amplification) as existing ranked maintenance. Composes withpreallocated(drained groups stay rankable at 0).documents.ranked({ groupBy: '<prefix property>' })dispatches when the group property matches a declaredatlevel; proofs ride the existing indexed-axis PathQuery surface (refactor(drive)!: route ranked and having-range proofs through grovedb's unified PathQuery surface #4488).Smaller independent sibling
Relaxing the exact-index-match rule to allow prefix-pinned count queries (
count WHERE hashtag == Xon[hashtag, postId]) would expose the already-maintained totals as point lookups (e.g. a "likes received" profile stat) even before ranking ships.Context
Verified against a live 4.2.0-dev.5 devnet with an indexOnly likes contract modeled on the pinned fixture: group-level ranking, structural uniqueness, and the prefix-count refusal all behave as described (exact error/behavior notes available on request). This is the last structural gap for like-derived discovery surfaces on the indexOnly shape — everything else (counts, membership with absence proofs, group-level top-K, delete-by-values) works end to end.