Skip to content

fix(analytics): sort dataset selections by the display label for select/lookup dimensions (#3680) - #3693

Merged
os-zhuang merged 1 commit into
mainfrom
claude/dataset-order-sort-issue-dqx9f3
Jul 27, 2026
Merged

fix(analytics): sort dataset selections by the display label for select/lookup dimensions (#3680)#3693
os-zhuang merged 1 commit into
mainfrom
claude/dataset-order-sort-issue-dqx9f3

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes#3680.

问题

DatasetSelection.order(widget options.sortBy 降级到的排序)按维度的存储值排序,而响应行里 select/lookup 维度已被改写为显示 label。于是 "按客户排序" 实际按不透明的 FK id 排序,用户看到的是一列乱序的名字;本地化 select 按 ASCII value 排序、显示的却是中文 label。

方案(issue 中 Option 2 的变体)

不把 label 解析整体搬进 executor,而是给它注入一个窄接口 OrderLabelResolver——只在排序键指向 label 承载型维度(select / lookup / master_detail)时,提供 值→label 的映射,仅比较时替换排序键

  • queryDataset 用与展示阶段完全相同的 label 能力构建该 hook(含 analytics: 让 executeAggregate 桥携带 ExecutionContext(#3597 的纵深防御第二层)+ 两处残留无 scope 调用 #3602 的被引用对象 read scope,scope 解析失败时 fail-closed 回退为按存储值排序,与展示阶段渲染原始 id 的行为一致),executor 保持 engine-free(纯注入接口)。
  • 行数据在展示阶段之前仍保持原始存储值,drill 元数据(drillRawRows 等)继续快照存储值,不受影响。
  • label 在 applyWindow之前解析,排序与窗口化保持相邻一步——"按客户名取前 10" 截取的是正确的 10 行。
  • 此类排序键不再下推 SQL 窗口(label 不是数据库列);其余情况的下推行为不变。

性能

  • 按 measure / 普通维度 / 日期桶排序(绝大多数场景):零开销,路径与 SQL 下推完全不变。

  • select 维度:映射来自字段元数据,不发查询。

  • lookup 维度:一次批量 id→name 读取,作用于窗口化前的分组去重值(分组结果的基数,通常远小于行数)。新增两项配套:

    • 每请求 label 缓存(withLabelFetchCache):展示阶段复用排序阶段已取的 id,整个请求只有一次 id→name 查询;
    • 插件端 fetchRecordLabels$in 按 500 个 id 分批,防止高基数 lookup 突破驱动的绑定参数上限(SQLite 历史下限 999)。

    剩余的固有成本:按 label 排序时全量分组网格需留在内存中排序+窗口化(数据库不存 label,无法让它排)。这与 ObjectQL 聚合路径今天的行为相同,且仅在真的按 lookup/select 维度排序时才发生。

测试

  • 新增 dataset-order-labels.test.ts(10 个用例):lookup 按名称排序 + drill 对齐、未解析 id 回退原值、select 按 label 反转序、top-N 先排后截 + 单次取数、label 键不下推 / measure 键仍下推、scope 透传与 fail-closed、applyOrdering 替换映射单测。
  • service-analytics 全套 19 文件 243 用例通过;analytics-label-scope dogfood(真实 RLS 端到端)通过。
  • 同步更新 dashboards 指南的 sortBy 行为说明,并附 changeset。

🤖 Generated with Claude Code

https://claude.ai/code/session_016ZsNHvYoujMGq66RLrCice


Generated by Claude Code

…ct/lookup dimensions (#3680)
`DatasetSelection.order` sorted a select/lookup dimension by its stored
value (option value / FK id) while the response renders the resolved
display label, so "sort by Account" presented as arbitrary. Order keys
naming a label-bearing dimension now sort by the label the user reads:
- `queryDataset` builds an `OrderLabelResolver` over the same label
capabilities (and #3602 referenced-object read scope, fail-closed) as
the display pass and injects it into the executor, which stays
engine-free.
- The executor substitutes the label as the SORT KEY only — rows keep
raw values for the drill sidecars — and resolves it before
`applyWindow`, so a "top 10 by account name" truncates the right ten.
Such keys are excluded from SQL window pushdown.
- A per-request label-fetch cache makes the display pass reuse the ids
the sort already fetched (one id→name read total), and the plugin's
`fetchRecordLabels` now chunks its `$in` (500/batch) since the sort
pass hands over the PRE-window id set.
- Measure / plain-dimension / date-bucket ordering is unchanged,
pushdown included.
Closes#3680.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZsNHvYoujMGq66RLrCice
@vercel

vercelBot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 27, 2026 2:39pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/l labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/services.

6 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/automation/webhooks.mdx(via packages/services)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/index.mdx(via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/plugins/packages.mdx(via packages/services)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 27, 2026 14:59
@os-zhuang
os-zhuang merged commit 3167e29 into mainJul 27, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/dataset-order-sort-issue-dqx9f3 branch July 27, 2026 14:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dataset order sorts a select/lookup dimension by its stored value, not the label the user reads

2 participants

@os-zhuang@claude