You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Bookshelf.js实现关联表分页:限制主模型与关联子模型数量

解决Bookshelf.js中主模型分页同时限制每个关联子模型数量的问题

你遇到的这个坑我之前也踩过!问题出在Bookshelf处理关联查询的逻辑上:你在withRelated里加的qb.limit(10)是全局限制所有关联书籍的总数量,而不是给每个作者单独限制10本。所以数据库会先把10个作者的所有关联书籍查出来,然后只取前10条,再把这些书分配给对应的作者,自然就出现了有的作者分到几本、有的空着的情况。

下面给你三种可行的解决方案,按需选择:

1. 用Knex窗口函数(性能最优,推荐)

利用SQL的窗口函数ROW_NUMBER()给每个作者的书籍分组编号,然后只保留每个组的前10本。通过Bookshelf的query()方法可以直接嵌入这个复杂逻辑:

Author.where('postedBy', userId)
  .fetchPage({ 
    pageSize: 10, 
    page: 1,
    withRelated: [
      {
        'books': function(qb) {
          qb.select('books.*')
            .from(function() {
              // 先给每个作者的书籍排序并编号
              this.select(
                'books.*', 
                knex.raw('ROW_NUMBER() OVER (PARTITION BY books.author_id ORDER BY books.id DESC) as row_num')
              )
              .from('books')
              .as('ranked_books');
            })
            // 只保留每个作者的前10本
            .where('row_num', '<=', 10);
        }
      }
    ]
  });

注意把ORDER BY books.id DESC换成你实际需要的排序规则(比如按出版时间排序),这样每个作者的书籍就是你想要的顺序,且最多10本。

2. 在模型关联中固定限制(适合数量不变的场景)

如果每个作者关联的书籍数量固定是10,直接在Author模型的关联定义里加限制更省事:

// Author模型的关联定义
books() {
  // 这里可以加排序和固定的limit
  return this.hasMany(Book).orderBy('id', 'desc').limit(10);
}

之后查询时就不用在withRelated里额外处理了:

Author.where('postedBy', userId)
  .fetchPage({ pageSize: 10, page: 1, withRelated: ['books'] });

缺点是这个限制是硬编码的,没法在每次查询时动态调整数量。

3. 手动加载关联(逻辑最直观,适合小数据量)

先分页查出10个作者,再逐个给每个作者加载前10本书籍。虽然要多做几次查询,但逻辑简单易懂,调试也方便:

// 第一步:分页获取10个作者
const authors = await Author.where('postedBy', userId)
  .fetchPage({ pageSize: 10, page: 1 });

// 第二步:批量给每个作者加载前10本books
await Promise.all(authors.models.map(async (author) => {
  const books = await author.related('books')
    .query(qb => qb.limit(10).orderBy('id', 'desc'))
    .fetch();
  author.set('books', books);
}));

// 现在每个作者都带了最多10本books
console.log(authors.toJSON());

这种方法适合作者数量不多的场景(比如你这里的10个),如果一次查几百个作者,多次查询的性能开销会比较明显。


内容的提问来源于stack exchange,提问作者Egor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:25:48