Flattened Smart Action - Partially Supported on Lists

Feature(s) impacted

Flattened Smart Fields rendering on Lists (and in general on the “Get List” route handlers).

Observed behavior

When a smart field is defined on a flattened record (i.e under some root and using the “@@@” separator) the data of the smart field is not calculated/retrieved with a list load command - only on an individual record data loads.

fa_br_1 ‑ Made with RecordCast (1)

Expected behavior

The Smart Field should work like all smart fields.

Context

Assume the following example schema:

const managerSchema = new Schema({
  first_name: String,
  last_name: String,
});

const mainSchema = new Schema({
  manager: managerSchema,
});

export default Schema(mainSchema);

Assume the following Liana collection configuration:

Liana.collection('Team', {
  fields: [
    {
      field: 'manager@@@full_name',
      type: 'String',
      get: (record) => {
        return record.manager
          ? record.manager.first_name + ' ' + record.manager.last_name
          : 'no manager';
      },
    },
  ],
  actions: [],
  segments: [],
  fieldsToFlatten: ['manager'],
});

Note - “manager” is flattened and “manager@@@full_name” is a smart field.

Additional Research

Diving into the code in forest-express-mongoose - Specifically in the Projection Builder it does seem like the method findRequestSmartField in the following section:

return this.schemaSmartFields
        .filter((fieldName) => requestFieldsNames.includes(fieldName));

has a problem finding Smart Fields which are nested. the “requestFieldNames” at this point only contains “root” properties - but the “Smart Field” is defined like so:

{
  field: 'someRootProp@@@calced_field'
}

This (maybe non standard way) of defining Smart Fields in a nested path works fine in other places in the system and the nesting is perfect - but I guess here in the Resources-Getter code tree things do not expect this.
I am looking for a workaround.

Additional Research

The top middleware here is requestUnflattener which “hides” from the normal Liana pipeline the flattened fields coming in from the query. It replaces them with the “root” field.

This works fine for query building and parsing since specifying “rootField” will bring in any sub field/documents which is good enough for the flattener to fo “flattening” on the outbound data pipeline.

But, when it comes to Smart Fields that are explicitly defined using the internal “@@@” separator - they are not detected and the Deserializer would not be able to “know” they are part of the request.

In forest-express-mongoose - Specifically in the “Projection Builder” the method findRequestSmartField has the following section:

return this.schemaSmartFields
        .filter((fieldName) => requestFieldsNames.includes(fieldName));

Finding Smart Fields which are nested requires them to be on the requestFieldsNames. The “requestFieldNames” at this point only contains “root” properties.

Suggested approach for solution

  • extend the requestUnflattener such that any fields that have been replaced by their parent will be preserved on a new “param” called "unflattenedFields` - this will have the original names as sent with the ‘@@@’
  • Extend the ResourceSerializer to accept an additional parameter unflattenedFields that will be appended to the fieldsPerModel param sent to SmartFieldsValuesInjector so it can “find” smart fields to calculate based on that field.
  • Another fix to cover all bases would be to fix the QueryBuilder so it can append those same field to the ones sent to ProjectionBuilder so it can run the findRequestSmartField method on them and disable the projection (so to get all fields that a SmartField might use)

Workaround for now

I am moving all smart fields to root :smile:
Meaning - I am not defining smart fields with “@@@” in them.
In the above example I would define a smart field like so:

{
      field: 'manager_full_name',
      type: 'String',
      get: (record) => {
        return record.manager
          ? record.manager.first_name + ' ' + record.manager.last_name
          : 'no manager';
      },
    },

Env

  • Project name: WescoverContentAdmin
  • Environment name: Private Development
"meta": {
    "liana": "forest-express-mongoose",
    "liana_version": "8.7.6",
    "stack": {
      "database_type": "multiple",
      "engine": "nodejs",
      "engine_version": "16.18.0",
      "orm_version": "5.9.29"
    }
  }

Thanks!

Hello @Yoad_Snapir ,
Thanks for reaching out to us, and for the details provided.
We have been trying to reproduce the issue but to no avail currently. We keep investigating and will let you know.
Could you please elaborate on the workaround that you are using currently. I’m not sure I understand fully what you are doing with the smart fields.

Thanks,

Regards,

Nicolas Moreau

@Nicolas.M Sorry for the mess - I was writing the post the way I researched it so it got confusing. I rewrite this one - now it should be clear what is the observed problem and what is my workaround.

Hello @Yoad_Snapir

Sorry for the answer delay.

Thank you again for you great explanations and reproducible steps.
It’s great that you found a workaround. The bug fix looking not easy, it will probably not be prioritized in the near future.

Regards,
Nicolas