How do I make this filter work on GraphQL query resolver extension

System Information
  • Strapi Version: 4.1.5
  • Operating System: macOS Big Sur
  • Database: MySQL
  • Node Version: 16.14.0
  • Yarn Version: 1.22.18

I have a collection type called Teacher Profiles. And I am adding an extra field in the query response that I calculate on the fly. This field doesn’t exist in the original content type. I am adding this using extension in file .src/index.js.

The field is being added successfully and I am able to receive it in the response.

But the problem is that I can’t filter records based on this field.

./src/index.js

"use strict";

const { NotFoundError } = require("@strapi/utils").errors;

module.exports = {
  register: ({ strapi }) => {
    const { transformArgs, getContentTypeArgs } = strapi
      .plugin("graphql")
      .service("builders").utils;
    const extensionService = strapi.plugin("graphql").service("extension");

    const extension = ({ nexus }) => ({
      types: [
        nexus.extendType({
          type: "TeacherProfile",
          definition(t) {
            t.int("minimum_hourly_rate");
          },
        }),
        nexus.extendInputType({
          type: "TeacherProfileFiltersInput",
          definition(t) {
            t.field("minimum_hourly_rate", {
              type: "IntFilterInput",
            });
          },
        }),
        nexus.extendType({
          type: "Query",
          definition(t) {
            t.field("teacherProfiles", {
              type: "TeacherProfileEntityResponseCollection",
              args: getContentTypeArgs(
                strapi.contentTypes["api::teacher-profile.teacher-profile"]
              ),
              async resolve(parent, args, ctx) {
                const transformedArgs = transformArgs(args, {
                  contentType:
                    strapi.contentTypes["api::teacher-profile.teacher-profile"],
                  usePagination: true,
                });

                const teacherProfiles = await strapi.entityService.findMany(
                  "api::teacher-profile.teacher-profile",
                  transformedArgs
                );

                const { toEntityResponseCollection } = strapi
                  .plugin("graphql")
                  .service("format").returnTypes;

                const transformedTeacherProfiles = teacherProfiles.map(
                  (teacherProfile) => {
                    return {
                      ...teacherProfile,
                      minimum_hourly_rate:
                        Math.floor(Math.random() * (40 - 30 + 1)) + 30,
                      // Math.random won't be actually used - it is just to demonstrate that I'll do some calculation here and
                      // value can vary
                    };
                  }
                );

                if (transformedTeacherProfiles) {
                  return toEntityResponseCollection(
                    transformedTeacherProfiles,
                    {
                      args: transformedArgs,
                      resourceUID: "api::teacher-profile.teacher-profile",
                    }
                  );
                } else {
                  throw NotFoundError();
                }
              },
            });
          },
        }),
      ],
    });

    extensionService.use(extension);
  },
};

When I send these filters with the query:

{
  "filters": { "minimum_hourly_rate": { "lte": 30}},
  "pagination": { "limit": 2}
}

And console log args, it gives:

{
  filters: { minimum_hourly_rate: { lte: 30 } },
  pagination: { limit: 2 },
  sort: []
}

This is correct. But when I console log the transformedArgs, it gives:

{ sort: [], start: 0, limit: 2, filters: {} }

When there is a field in the filters that is not present in the content type schema, it doesn’t get transformed. Which is probably correct, as transform function compares given args to the content type schema.

If I mutate the transformedArgs, and manually add the minimum_hourly_rate value in it, then I give it to:

strapi.entityService.findMany(
    "api::teacher-profile.teacher-profile", mutatedTransformedArgs
);

This also gives an error:

Error: ER_BAD_FIELD_ERROR: Unknown column 't0.minimum_hourly_rate' in 'where clause'

This is also correct as Strapi entity service doesn’t know about this field minimum_hourly_rate. (it doesn’t exist on the original schema).

So, my question is basically how do I filter records based on this filter? For example, I want to retrieve 15 records where minimum_hourly_rate < 30. Thanks!

@DMehaffy & @Convly, sorry to tag you guys, but can you please shed some light on this?