Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual attributes are ignored inside the include section #10552

Closed
exsesx opened this issue Mar 14, 2019 · 13 comments
Closed

Virtual attributes are ignored inside the include section #10552

exsesx opened this issue Mar 14, 2019 · 13 comments

Comments

@exsesx
Copy link

exsesx commented Mar 14, 2019

What am I doing?

await Question.findAll({
  attributes: ['id', 'name'],
  include: {
    model: Video,
    attributes: ['id', '...', 'resourceUrl'], // resourceUrl - virtual string type
    include: {
      model: Image,
      as: 'poster',
      attributes: ['id', '...', 'resourceUrl'], // resourceUrl here - virtual string type too
    },
  },
})

What do I expect to happen?

I expected the Video and Poster models to have the attribute "resourceUrl"

What is actually happening?

But all specified attributes returned except the virtual ones...

Dialect: postgres
Dialect version: 7.8.2
Database version: 10.7
Sequelize version: 5.1.0
Tested with latest release: Yes, 5.1.0 (If yes, specify that version)

@SimonSchick
Copy link
Contributor

Can you please post a minimal repro?

@exsesx
Copy link
Author

exsesx commented Mar 15, 2019

Off course, @SimonSchick

I have three models:

Question

// models/question.js

module.exports = (sequelize, DataTypes) => {
  const Question = sequelize.define('question', {
    code: {
      type: DataTypes.STRING,
      unique: true,
    },
  }, {
    timestamps: false,
    indexes: [
      {
        fields: ['categoryId', 'code'],
        unique: true,
      },
    ],
  })

  Question.associate = function (models) {
    // ... Associations
    Question.hasMany(models.video)
    // ... Associations
  }
  return Question
}

Video

// models/video.js

const { getResourceUrl } = require('../helpers/models')

module.exports = (sequelize, DataTypes) => {
  const Video = sequelize.define(
    'video',
    {
      name: {
        type: DataTypes.STRING,
      },
      path: {
        type: DataTypes.UUID,
        unique: true,
      },
      resourceUrl: {
        type: DataTypes.VIRTUAL(DataTypes.STRING, ['path']),
        get () {
          return getResourceUrl.call(this, sequelize)
        },
        validate: { isUrl: true },
      },
      // Fields...
    },
    {
      hooks: {
        // Hooks
      },
    }
  )

  // Model static & prototype functions...

  Video.associate = function (models) {
    const {
      // Models...
      question: Question,
      image: Image,
      // Models...
    } = models

    Video.hasOne(Image, { onDelete: 'cascade', as: 'poster', foreignKey: 'videoId' })
    Video.belongsTo(Question)

    // Associations...
  }

  return Video
}

Image

const { getResourceUrl } = require('../helpers/models')

module.exports = (sequelize, DataTypes) => {
  const Image = sequelize.define('image', {
    path: {
      type: DataTypes.STRING,
      unique: true,
    },
    resourceUrl: {
      type: DataTypes.VIRTUAL(DataTypes.STRING, ['path']),
      get () {
        return getResourceUrl.call(this, sequelize)
      },
      validate: { isUrl: true },
    },
  }, {
    indexes: [ /* Unique indexes... */ ],
    validate: {
      // Validations
    },
    timestamps: false,
  })
  Image.associate = function (models) {
    Image.belongsTo(models.video)
  }

  return Image
}

As you can see Image and Video models have virtual data type field ("resourceUrl").

And the problem is, when I run the query described above, included models don’t have virtual types even if I specify them inside options.attributes: [/* ... fields ... */ 'virtualField']


P.S. Here's my observation: If I don't specify options.attributes at all or start writing the query from the Video model* - the query works fine.

The working query example:

Video.findOne({
  attributes: ['id', 'path'] // we don't have to add virtual column here
  // ...
})

@nwalters512
Copy link

This seems to be a regression in v5.x - we just updated from v4.42.0 and this was working as expected.

@exsesx
Copy link
Author

exsesx commented Mar 25, 2019

I still have the same issue on 5.1.1, waiting for the fix.

@exsesx exsesx changed the title Virtual attributes are ignored inside the include section (5.2.0) Virtual attributes are ignored inside the include section Mar 26, 2019
@exsesx exsesx changed the title (5.2.0) Virtual attributes are ignored inside the include section (^5.2.0) Virtual attributes are ignored inside the include section Apr 8, 2019
@danconnell
Copy link
Contributor

Reproducible on 5.6.0

@danconnell
Copy link
Contributor

Submitted a fix #10785

@sushantdhiman
Copy link
Contributor

Fixed #10785

@exsesx exsesx changed the title (^5.2.0) Virtual attributes are ignored inside the include section Virtual attributes are ignored inside the include section Apr 17, 2019
@exsesx
Copy link
Author

exsesx commented Apr 17, 2019

Thanks!

@jetpack3331
Copy link

jetpack3331 commented May 19, 2019

I'm trying this approach in 5.8.0 but there should be next error.

I have defined Virtual field in model A like this:

HasSomething: {
      type: Sequelize.VIRTUAL(Sequelize.BOOLEAN, [
        sequelizeConfig.literal(`
          (SELECT (COUNT(*)::int)::bool AS "HasSomething"
          FROM table)
        `)
      ])
    }

Then i'm calling Model B which should include Model A as array of these models via:

ModelB.findAll({
    include: [
    	{
    		model: ModelA,
    		as: 'ModelsA',
    		attributes: [
    			'HasSomething',
    			...Object.keys(ModelA.rawAttributes)
    		]
    	}
    ]
})

It's properly called but it's not in the result. Any idea?

@jeff-pal
Copy link

Some solution? I'm having this problem with postgresql. So when I was using mysql it was running fine, but then I changed to postgres and then I'm facing this problem. The following attributes are being ignored:

User.findByPk(req.params.userUuid, { 
        include: { 
          model: Company, 
          as: 'company', 
          include: [
            {
              model: CompanyType, 
              as: 'type'
            }, 
            {
              model: Fowarder, 
              as: 'fowarder', 
              include: {model: FowarderService, as: 'fowarder_services',
                through: {
                  attributes: ['fowarder_applied_service_uuid', 'fowarder_uuid', 'fowarder_service_uuid']
                }
              }
            }
          ] 
      }});

@JacquesMironneau
Copy link

Same problem on postgresql, any fix ?

@askynet
Copy link

askynet commented Dec 20, 2021

I'm also facing the same problem on postgresql, any workaround?

@JacquesMironneau
Copy link

@askynet mine was to do another request with the id of the included field to get virtual fields through it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants