TSts-grm

排序

排序在查询回调里用 q.orderBy(...) 声明,可传多列、可对表达式排序。

单列与升降序

// ① 模型准备(完整可运行版见工作区)
import { model, prop, dto } from '@ts-grm/core'
import { sqlClient } from './infra/sql-client'

const Book = model("Book", "id", class {
    id = prop.i64()
    name = prop.str(50)
    edition = prop.i32()
    price = prop.num(10, 2)
})

const BookView = dto.view(Book, c => [c.id, c.name, c.edition, c.price])

const rows = await sqlClient.createQuery(Book, (q, book) => {
    q.orderBy(book.price.desc())         // 降序;asc() 是默认,可省
    return q.select(book.fetch(BookView))
}).fetchList()

console.log(rows)

多列与混合方向

// ② 多列:先 name 升序(默认),同名的按 edition 降序
const rows2 = await sqlClient.createQuery(Book, (q, book) => {
    q.orderBy(book.name, book.edition.desc())
    return q.select(book.fetch(BookView))
}).fetchList()

console.log(rows2)

顺序即优先级:前面的列为主键级排序。orderBy 可多次调用(追加)。

表达式排序与子路径

  • embedded 子路径排序直接点路径:q.orderBy(author.name.lastName)
  • 关联键(引用外键)排序:q.orderBy(book.storeId)
  • 表达式/聚合排序q.orderBy(dsl.count().desc())(配合聚合与分组,见「聚合与分组」页)。

排序稳定性(重要)

fetchPage/fetchRange 按行切片取数——切片稳定依赖排序唯一性。只看一列排时,值相同的行在页与页之间顺序无保证。要分页/取 TopN,请补一个唯一键做决胜列:

q.orderBy(book.price.desc(), book.id.asc())   // 价格 + id 决胜,页间不漂移

下一步

筛选、排序都齐了。下一节是查询组的高地:取形进阶——扁平化、折叠、递归、输出映射与多态分支。