adonis-lucid-polymorphic icon indicating copy to clipboard operation
adonis-lucid-polymorphic copied to clipboard

Trying to eagerload relationship twice by using multiple with(), different relationships

Open fokoz opened this issue 5 years ago • 7 comments

Package version

6.1.3

Node.js and npm version

9.1.0 and 6.4.1

Sample Code (to reproduce the issue)

Getting this error: E_CANNOT_OVERRIDE_RELATION: Trying to eagerload headChef relationship twice

When I try to fetch multiple with: await Kitchen.query().with('headChef').with('chef').fetch()

both headChef() and chef() belongs to the same model App/Models/Chef but using different id (head_chef_id, chef_id)

fokoz avatar Sep 18 '19 10:09 fokoz

Same here

e200 avatar Dec 01 '19 18:12 e200

I have the same problem and "with" doesn't work when you add a filter (where)...

this is a dead proyect @enniel ?

cognitus avatar Jan 26 '20 00:01 cognitus

For those who faced this issue could try to use my modified code here: src/EagerLoad/index.js

'use strict'

const _ = require('lodash')
const BaseEagerLoad = require('@adonisjs/lucid/src/Lucid/EagerLoad')
const RelationsParser = require('@adonisjs/lucid/src/Lucid/Relations/Parser')

class EagerLoad extends BaseEagerLoad {
  /**
   * Load relationships for all the model instances and set
   * relationships on the model instances using @ref('Model.setRelated')
   *
   * @method load
   *
   * @param  {Array} modelInstances
   *
   * @return {void}
   */
  async load (modelInstances) {
    const groupedRelations = _.reduce(modelInstances, (result, modelInstance) => {
      _.each(this._relations, (attributes, relation) => {
        RelationsParser.validateRelationExistence(modelInstance, relation)
        const relationInstance = RelationsParser.getRelatedInstance(modelInstance, relation)
        this._applyRuntimeConstraints(relationInstance, attributes.callback)
        this._chainNested(relationInstance, attributes.nested)
        const RelatedModel = relationInstance.RelatedModel
        const groupName = RelatedModel.name

        if (!result[relation]) {
          result[relation] = {
            relation,
            relationInstance: null,
            modelInstances: []
          }
        }
        result[relation].relationInstance = relationInstance
        result[relation].modelInstances.push(modelInstance)
      })
      return result
    }, {})


    /**
     * An array of queries to be executed queries parallel
     */
    const queries = _.map(groupedRelations, (group) => {
      return group.relationInstance.eagerLoad(group.modelInstances)
    })

    const relatedModelsGroup = await Promise.all(queries)
    /**
     * Here we have an array of different relations for multiple parent
     * records. What we need is to fetch the parent level record and
     * set relationships for each relation on it. Same is done
     * for all parent records.
     */
    _.each(Object.keys(groupedRelations), (key, index) => {

      const { relation, modelInstances } = groupedRelations[key]
      const relationGroups = relatedModelsGroup[index]

      /**
       * We should loop over actual data set and not the resolved relations.
       * There are chances when actual relation set will have more rows
       * than relations, in that case we need to set relations to
       * `null` or whatever the default value is.
       */
      _.each(modelInstances, (modelInstance) => {
        /**
         * Find the actual value of the relationship for that model instances
         */
        const value = relationGroups.values.find((group) => {
          return group.identity === modelInstance[relationGroups.key]
        }) || { value: relationGroups.defaultValue }

        /**
         * Setting relationship on the parent model instance
         */
        modelInstance.setRelated(relation, value.value)
      })
    })
  }
}

module.exports = EagerLoad

fokoz avatar Apr 13 '20 19:04 fokoz

@fokoz can you do a fork with that code?

cognitus avatar Apr 14 '20 19:04 cognitus

@cognitus I didn't test with filter where but I think it should work. Could you try to use my code, if it works I will fork it.

fokoz avatar Apr 15 '20 16:04 fokoz

When will this be fixed ?

prince-vishal avatar Sep 15 '20 21:09 prince-vishal

but why....

shanthakumarf22 avatar Dec 16 '20 11:12 shanthakumarf22