Strapi V4 handle pagination in GraphQL custom resolver

System Information
  • Strapi Version: 4.4.1
  • Operating System: macOS Ventura
  • Database: postgreSql
  • Node Version: 16.14.0
  • NPM Version: 8.5.5
  • Yarn Version:

Hi,

I’m trying to create a custom resolver that handle pagination, I’m getting my data correctly but I miss the “meta data” of pagination. I don’t know how to extract meta data of pagination using the strapi service.

Here is my resolver :

{
      t.field("studyMots", {
        type: "StudyMotEntityResponseCollection",
        args: { filters: "StudyMotFiltersInput", pagination: "PaginationArg" },
        async resolve(parent, args, ctx) {
          const userId: string = ctx?.state?.user?.id;

          if (!userId) {
            throw new Error("Unauthorize");
          }

          const {
            filters,
            pagination: { page, pageSize } = {
              page: 0,
              pageSize: DEFAULT_SIZE_PAGE,
            },
          } = args;

          const start = page * pageSize;
          const limit = pageSize;
          const studyMotsResponse = await strapi.entityService.findMany(
            "api::study-mot.study-mot",
            {
              filters: {
                ...filters,
                user: userId,
              },
              start,
              limit,
            }
          );
          return toEntityResponseCollection(studyMotsResponse);
        },
      });
    }

This is what I’m looking for :

Thanks in advance for help

I found some answers but I have more questions now. I found that I have to use function “findPage()” to get pagination data.

But when I use “start” and “limit” parameters, they are not taken into account. All my entites are returned.

 const { results: studyMotsResponse, pagination: pageResult } =
            await strapi.entityService.findPage("api::study-mot.study-mot", {
              filters: {
                ...filters,
                user: userId,
              },
              start,
              limit,
            });

          console.log(pageResult);

          return toEntityResponseCollection(studyMotsResponse);
      // start:0  limit:5
      // log => { page: 1, pageSize: 10, pageCount: 1, total: 10 }

Does I have to use other parameters ?

Another question how can I return my pagination meta data from my resolver ?

Some help please

I am in urgent need of this solution.
Cant get meta data from entityService.findMany and entityService.findPage ignores start and limit properties.
help please.

1 Like

I found how to get my paginated results and pagination meta data, now I don’t know how to return this pagination meta data from my custom resolver.

This is whate I’m doing right now :

const { results, pagination } = await strapi.entityService.findPage(
            "api::XXXX.XXXX",
            {
              filters: {
                ...filters,
                user: userId,
              },
              page,
              pageSize,
            }
          );

          return toEntityResponseCollection(results);

How can I return my pagination meta data ?

we can’t rely on this forum, can we? very bad.

Note sure if this is relevant, but since you seem stuck perhaps this custom REST API controller could give you some insights. I use it with the following query: /api/lists/library?pagination[page]=1&pagination[pageSize]=15

async library(ctx) {
  const { results, pagination } = await strapi.service("api::list.list").find({
    sort: ["updatedAt:desc"],
    populate: ["author.profile", "cover"],
    pagination: ctx.request.query?.pagination || {},
  })


  ctx.send({ results, pagination })
}

If not, I would recommend looking into the core service package and cherry-pick the individual functions needed.

we can’t rely on this forum, can we? very bad.

Agree 100 %. The Community (slack and forum) are the worst part of Strapi, and probably their biggest weakness in the long run. I’m just waiting for an equally robust alternative and I’m gone.

Thank you brother, I finallly found a solution by looking in strapi repository directly.

The “meta” object which contains pagination details is handled by strapi it self using a resolver and it need us to provide resourceUID , start and limit. So we don’t need to use findPage method findMany is enough.

ResponseCollectionMeta: objectType({
      name: RESPONSE_COLLECTION_META_TYPE_NAME,

      definition(t) {
        t.nonNull.field('pagination', {
          type: PAGINATION_TYPE_NAME,

          async resolve(parent) {
            const { args, resourceUID } = parent;
            const { start, limit } = args;
            const safeLimit = Math.max(limit, 1);

            const total = await strapi.entityService.count(resourceUID, args);
            const pageSize = limit === -1 ? total - start : safeLimit;
            const pageCount = limit === -1 ? safeLimit : Math.ceil(total / safeLimit);
            const page = limit === -1 ? safeLimit : Math.floor(start / safeLimit) + 1;

            return { total, page, pageSize, pageCount };
          },
        });
      },

So the key is to return something like this at the end of our custom resolver :

return toEntityResponseCollection(results, {
            args: { start, limit },
            resourceUID: "api::XXXX.XXXX",
          });
1 Like

Posting this, as it took a little bit to get a working solution still, create a custom resolver in /src/api/index.js

          pages: {
            resolve: async (obj, options, ctx) => {
              const { toEntityResponseCollection } = strapi.service(
                "plugin::graphql.format"
              ).returnTypes;

              const data = await strapi.service(
                "api::page.page"
              ).find(options);
              const start = options.start || 0;
              const limit = options.limit || 100;
              const response = toEntityResponseCollection(data.results, {
                args: { start, limit },
                resourceUID: "api::page.page",
              })
              return response;
            },
          },```
This is using the find service, which you can edit or extend. With this resolver you can pass in logic to that service and also get the meta data and pagination.
1 Like