Calculated Fields using related data


#1

I am trying to figure out the best way to handle calculated fields that leverage related data. Below is a hypothetical situation…

App/Models/Parent

'use strict'

const Model = use('Model')
class Parent extends Model {
  children() {
    return this.hasMany('App/Models/child', 'id', 'parent_id')
  }
  anotherRelatedObject() {
    return this.hasOne('App/Models/AnotherRelatedObject')
  }
  /**
   Fields:
   ParentField
   anotherRelatedObject_id
   CalculatedParentField = sum(children.ChildField2)
   **/
}
module.exports = Parent

App/Models/Child

'use strict'

const Model = use('Model')
class Child extends Model {
  parent() {
    return this.belongsTo('App/Models/Parent')
  }
  /**
   Fields:
   Parent_id
   ChildField1
   ChildField2
   CalculatedChildField1 = ChildField1 * parent.anotherRelatedObject.Field
   CalculatedChildField2 = ChildField1 * parent.ParentField
   **/
}
module.exports = Child

App/Models/AnotherRelatedObject

'use strict'

const Model = use('Model')
class AnotherRelatedObject extends Model {
}
module.exports = AnotherRelatedObject

What would be the best method for calculated values on the child records using fields from the parent record or using fields from a record related to the parent? My goal would be to have these values populated when executing the toJSON() method on the model (serilaizer). Should I do this via traits? Computed properties? Or should I just create a custom serializer with raw() queries to the DB and calculate them as part of the query?

Any help would be much appreciated, and thanks in advance.


#2

Update on this, you cannot use Computed Properties. You would need to hit the DB to find the parent the Computed Property just returns an unresolved promise because it appears computed properties do not handle async functions.

If you were to add:

const Parent = use(‘App/Models/Parent’)

and then

static get computed () {
return [‘getCalculatedChildField2’]
}

async getCalculatedChildField2({Parent_id, ChildField1}) {
return Parent.find(Parent_id)
.then(parent => {return parent.ParentField * ChildField1})
.catch(err => console.log(err))

CalculatedChildField2 would show up in the toJSON but would not be the correct value, it would be a the unresolved Promise response