Limit and order number of nested / relation entities fetched

Spent ages figuring this out so I thought I’d post here for future Googlers.

I am making a blog and I have categories and articles, both having a “content” dynamic zone. When fetching a single category, I was getting huge data from all the articles, since their content is quite long. In reality, I only need the most recent 6 or so, and I can fetch more later by querying articles.

autoPopulate seems to not work properly for dynamic zones. I could just not populate the articles of a category at all, but it seems a bit silly. In the end, I figured out the way to only populate the first 6 most recent articles without their content:

// services/category.js

module.exports = {
  find(params, populate) {
    return strapi
      .query("category")
      .find(params, [/* any category fields you DO want to populate when listing many categories*/]);
  },
  async findOne(params, populate) {
    const model = await strapi.query("category").model;
    const filters = convertRestQueryParams({ ...params, _limit: 1 });
    const query = buildQuery({ model, filters });

    return model
      .query(query)
      .fetchAll({
        withRelated: [
          {
            articles: (qb) => {
              qb.orderBy("published_at", "desc").limit(6);
            },
          },
          "articles.image", //this works
          /* any other fields you do want to populate*/
        ],
      })
      .then((results) => results.toJSON()[0] ?? null);
  },
}

I also set autoPopulate: false for articles in the categories model settings.