Filtering via REST on calculated fields? Is it possible?

Hi all!

I have calculated field - added on the fly in overriden find/findOne methods in a controller.
This works fine for field creation and it is accessible on my front-end.
But, when I want to filter by the same field via REST parameter - it does not work - like the filter is not even there.

Is this even possible?

Adding calculated fields on the fly (findOne):

async findOne(ctx) {
		const { nulls } = ctx.request.query
		const { data, meta } = await super.findOne(ctx)
		if (data) {
			data.attributes.__properties = {
				...helpers.processTextProperties(data.attributes.text_properties),
			}
			data.attributes.__currentPrice = getCurrentProductPrice(modifyResponseBodyData(null, data.attributes))
			if (!nulls) removeNullProperties(data)
			removeKeys(data, config.KEYS_TO_REMOVE)
		}
		return { data, meta }
	}

Added value is object where one of the object attributes is “new_price”.

REST filter:
http://localhost:1337/api/products?fields=*&filters[$and][0][__currentPrice][new_price][$gte]=789&filters[$and][1][__currentPrice][new_price][$lte]=790&pagination[page]=1&pagination[pageSize]=24&sort[name]=asc

This should work if you print it out in the service does it give you the correct infromatoin?

Yes - i get this “calculated” field in response from server - JSON is exactly as expected.
But when using in filter - no dice. That is the problem.

I am not sure what the issue could be if it populates fine and it is not in a dynamic zone it should work

1 Like

I wonder if this could be cause by that old issue where filters are messed up with what current user can see (is allowed to see) - even though this should be public for front-end use? And since this is calculated field (or virtual as some call it) - could that be a problem? Quite odd behavior anyway.

Could be that the query is senatized out. you can test it by calling the sanitize query manualy and checking the output.
see the following code from the docs Controllers | Strapi Documentation

const { sanitize, validate } = require('@strapi/utils');

module.exports = {
  async findCustom(ctx) {
    const contentType = strapi.contentType('api::test.test');
    await validate.contentAPI.query(ctx.query, contentType, { auth: ctx.state.auth });
    const sanitizedQueryParams = await sanitize.contentAPI.query(ctx.query, contentType, { auth: ctx.state.auth });

    const entities = await strapi.entityService.findMany(contentType.uid, sanitizedQueryParams);

    return await sanitize.contentAPI.output(entities, contentType, { auth: ctx.state.auth });
  }
}

Already checked - as I said, the query returns everything as expected - JSON in response contains this new field as part of each product item/entity. It just does not want to filter by it.