Mongoose - Flattened Field Type not considered in filters

Feature(s) impacted

Filters of Flattened fields which require parsing (like Date) are not working.

Observed behavior

The Date value string sent from the client is NOT converted to a Date by the lib and mongoose compares text to date and the filter is not working.
Non Flattened fields work as expected.

Expected behavior

Filters should work also for flattened fields.

Failure Logs

Consider the following filter sent from the client to a “list” endpoint:

{"aggregator":"and","conditions":[{"field":"monitoring_status","operator":"equal","value":"active"},{"field":"modified_at","operator":"before","value":"2023-11-27T07:29:54.576Z"},{"field":"conversation@@@last_msg_at","operator":"before","value":"2023-11-26T07:29:54.576Z"}]}

The field “modified_at” is not flattened - the field “conversation.last_msg_at” is flattened.
The relevant Mongoose schema looks like this:

{ monitoring_status: String, modified_at: Date, conversation: { last_msg_at: Date } }

The output filter to mongodb looks like this:

 { '$match': { '$and': [ { '$and': [ { monitoring_status: 'active' }, { modified_at: { '$lt': **2023-11-27T07:35:33.662Z** } }, { 'conversation.last_msg_at': { '$lt': **'2023-11-26T07:35:33.662Z'** } } ] } ] } }

Note! one date value is a string and the other is an ISODate

Root cause

See the code here

this.formatCondition = async (condition, isSmartField = false) => {
    if (isSmartField) {
      return this.formatOperatorValue(
        condition.field,
        condition.operator,
        condition.value,
      );
    }

    const formatedField = this.formatField(condition.field);

    return {
//!==>
      [Flattener.unflattenFieldName(formatedField)]: await this.formatOperatorValue(
        condition.field, //<==!
        condition.operator,
        condition.value,
      ),
    };
  };

The field sent into the formatOperatorValue is not unflattened. Thus it cannot find that field in the schema and falls back to an unknown type and does no parsing on it.

this.formatOperatorValue = async (field, operator, value) => {
    if (this.operatorDateParser.isDateOperator(operator)) {
      return this.operatorDateParser.getDateFilter(operator, value);
    }

//!==>
    const parseFct = await this.getParserForField(field);
...

And

this.getParserForField = async (key) => {
    const [fieldName, subfieldName] = key.split(':');

    const field = SchemaUtils.getField(modelSchema, fieldName);

    if (!field) {
      throw new InvalidFiltersFormatError(`Field '${fieldName}' not found on collection '${modelSchema.name}'`);
    }

    const fieldPath = subfieldName ? `${fieldName}.${subfieldName}` : fieldName;
    const fieldType = **utils.getNestedFieldType**(model.schema, fieldPath);

//!==>
    if (!fieldType) return (val) => val;
...
};

Context

  • Project name: Not Project specific
  • Environment name: Not Env Specific
  • Agent (forest package) name & version: forest-mongoose-express versions 8+9
  • Database type: Mongodb

Thanks @Yoad_Snapir for this really details issue :pray:
I will create a bug ticket, we will let you know as soon as a fix has been released

1 Like

Hello @Yoad_Snapir
The fix is now available in forest-express-mongoose 9.3.14
Please let us know if the issue is fixed on your side :pray:

Regards,
@Nicolas.M

1 Like

This solved the problem.
Required upgrade to V9 so I will perform tests before deploying.
Thanks!

1 Like