Repository: directus/directus
File: api/src/database/run-ast/lib/apply-query/filter/operator.ts (TypeScript)

Code before:
	// conditionally build out your filter structure (#4471)
	if (compareValue === undefined) return;

	if (Array.isArray(compareValue)) {
		// Tip: when using a `[Type]` type in GraphQL, but don't provide the variable, it'll be
		// reported as [undefined].
		// We need to remove any undefined values, as they are useless
		compareValue = compareValue.filter((val) => val !== undefined);
	}

	// Cast filter value (compareValue) based on function used
	if (column!.includes('(') && column!.includes(')')) {
		const functionName = column!.split('(')[0] as FieldFunction;
		const type = getOutputTypeForFunction(functionName);

		if (['integer', 'float', 'decimal'].includes(type)) {
			if (Array.isArray(compareValue)) {
				compareValue = compareValue.map((val) => {
					const num = Number(val);
					if (Number.isNaN(num)) throw new InvalidQueryError({ reason: `Invalid numeric value` });
					return num;
				});
			} else {
				compareValue = Number(compareValue);
				if (Number.isNaN(compareValue)) throw new InvalidQueryError({ reason: `Invalid numeric value` });
			}
		}
	}

	// Cast filter value (compareValue) based on type of field being filtered against
	const [collection, field] = key.split('.');
	const mappedCollection = (originalCollectionName || collection)!;

	if (mappedCollection! in schema.collections && field! in schema.collections[mappedCollection]!.fields) {
		const type = schema.collections[mappedCollection]!.fields[field!]!.type;

		if (['date', 'dateTime', 'time', 'timestamp'].includes(type)) {
			if (Array.isArray(compareValue)) {
				compareValue = compareValue.map((val) => helpers.date.parse(val));
			} else {
				compareValue = helpers.date.parse(compareValue);
			}
		}

		if (['integer', 'float', 'decimal'].includes(type)) {
			if (Array.isArray(compareValue)) {
				compareValue = compareValue.map((val) => {
					const num = Number(val);
					if (Number.isNaN(num)) throw new InvalidQueryError({ reason: `Invalid numeric value` });
					return num;
				});

Review comment (refactor):
Nit: this is identical to be bottom changes so maybe reuse this with a function instead of having duplicate code here.

Code after:
	if ((operator === '_empty' && compareValue !== false) || (operator === '_nempty' && compareValue === false)) {
		dbQuery[logical].andWhere((query) => {
			query.whereNull(key).orWhere(key, '=', '');
		});
	}

	if ((operator === '_nempty' && compareValue !== false) || (operator === '_empty' && compareValue === false)) {
		dbQuery[logical].andWhere((query) => {
			query.whereNotNull(key).andWhere(key, '!=', '');
		});
	}

	// The following fields however, require a value to be run. If no value is passed, we
	// ignore them. This allows easier use in GraphQL, where you wouldn't be able to
	// conditionally build out your filter structure (#4471)
	if (compareValue === undefined) return;

	if (Array.isArray(compareValue)) {
		// Tip: when using a `[Type]` type in GraphQL, but don't provide the variable, it'll be
		// reported as [undefined].
		// We need to remove any undefined values, as they are useless
		compareValue = compareValue.filter((val) => val !== undefined);
	}

	// Cast filter value (compareValue) based on function used
	if (column!.includes('(') && column!.includes(')')) {
		const functionName = column!.split('(')[0] as FieldFunction;
		const type = getOutputTypeForFunction(functionName);

		if (['integer', 'float', 'decimal'].includes(type)) {
			compareValue = castToNumber(compareValue);
		}
	}

	// Cast filter value (compareValue) based on type of field being filtered against
	const [collection, field] = key.split('.');
	const mappedCollection = (originalCollectionName || collection)!;

	if (mappedCollection! in schema.collections && field! in schema.collections[mappedCollection]!.fields) {
		const type = schema.collections[mappedCollection]!.fields[field!]!.type;

		if (['date', 'dateTime', 'time', 'timestamp'].includes(type)) {
			if (Array.isArray(compareValue)) {
				compareValue = compareValue.map((val) => helpers.date.parse(val));
			} else {
				compareValue = helpers.date.parse(compareValue);
			}
		}

		if (['integer', 'float', 'decimal'].includes(type)) {
			compareValue = castToNumber(compareValue);