在 nest.js 中使用 typeorm querybuilder 查询关联数据时,可通过 `.limit()` 方法全局限制最终返回的实体总数;若需单独限制某一层级

TypeORM 的 .limit() 方法作用于整个查询结果集,即它会限制最终返回的 landingSectionName 实体数量(例如最多 10 条),而非限制关联表 category 的加载条目数。因此,以下写法:
async find() {
return this.landingSectionNameRepository.createQueryBuilder('landingSectionName')
.leftJoinAndSelect('landingSectionName.landingSectionCategory', 'landingSectionCategory')
.leftJoinAndSelect('landingSectionCategory.category', 'category')
.limit(10)
.getMany();
}✅ 正确实现了「最多获取 10 个 landingSectionName 及其完整关联数据」;
❌ 但不会让每个 category 关系只加载前 N 条——因为 category 是通过 leftJoinAndSelect 关联的单值关系(假设为 @ManyToOne),本身不涉及“多条 category”的场景;若实际是 @OneToMany(如一个分类下有多个子类),则需明确目标:是限制「每个父级关联的子项数量」,还是「全局 category 实体去重后的总数量」?
直接使用 .limit(n) + .offset(m) 实现分页:
async findWithPagination(take = 10, skip = 0) {
return this.landingSectionNameRepository.createQueryBuilder('landingSectionName')
.leftJoinAndSelect('landingSectionName.landingSectionCategory', 'landingSectionCategory')
.leftJoinAndSelect('landingSectionCategory.category', 'category')
.take(take)
.skip(skip)
.getMany();
}此时需改用子查询或原生 SQL,TypeORM 原生不支持 LIMIT PER GROUP。推荐方式是拆分为两步查询,或使用 @JoinTable + 显式子查询:
// 示例:获取每个 category 的最新 3 个 landingSectionCategory
async findWithLimitedCategories() {
const subQuery = this.landingSectionCategoryRepository
.createQueryBuilder('lsc')
.select(['lsc.id', 'lsc.categoryId', 'lsc.createdAt'])
.addSelect('ROW_NUMBER() OVER (PARTITION BY lsc.categoryId ORDER BY lsc.createdAt DESC) as rn')
.where('rn <= 3');
return this.landingSectionNameRepository.createQueryBuilder('lsn')
.innerJoin(
`(${subQuery.getQuery()})`,
'limitedLsc',
'limitedLsc.id = lsn.landingSectionCategoryId'
)
.leftJoinAndSelect('limitedLsc.category', 'category')
.setParameter('take', 3)
.getMany();
}⚠️ 注意:子查询语法依赖数据库类型(如 PostgreSQL 支持 ROW_NUMBER(),MySQL 8.0+ 同样支持,旧版需改用变量模拟)。
总之,.limit() 是主查询维度的“结果总数限制”,不是关系维度的“嵌套数据限额”。理解这一边界,才能写出高效、可维护的 Nest.js + TypeORM 数据访问层。