简体   繁体   English

当包含模型时,Sequelize 查询返回错误的行数 (findAndCountAll)

[英]Sequelize query returning the wrong number of rows when models are included (findAndCountAll)

The following code should return 12 rows ( req.query.limit = 12).以下代码应返回 12 行 ( req.query.limit = 12)。 This works fine if I don't include any associated rows, but when I include the related models it returns 7 rows.如果我不包含任何关联的行,这就可以正常工作,但是当我包含相关模型时,它会返回 7 行。

I think it's down to me using the property subQuery: false which allows me (if I remember correctly) to order my results by column correctly - but it's been a long time since I've looked at the ordering code, I'm not very proficient with sequelize, and don't want to break it unnecessarily!认为这取决于我使用属性subQuery: false这允许我(如果我没记错的话)按列正确地排序我的结果 - 但是我已经很长时间没有看过排序代码了,我不是很精通sequelize,不想无谓破坏!

Would really appreciate it if someone can spot where I'm going wrong, and maybe why?如果有人能发现我哪里出错了,我会非常感激,也许为什么?

exports.getApplications = async(req, res, next) => {
    const index = req.query.index || 0;
    const limit = req.query.limit || 10;
    const order = req.query.orderDirection || 'DESC';
    let orderFields;

    switch(req.query.orderField) {
        case 'lastName': 
            orderFields = [
                ['applicant', 'person', 'lastName'], 
                ['applicant', 'person', 'firstName'], 
 
                ['applicant', 'createdAt', order]

            ];
            break;
        
        default:
            orderFields = [ 'createdAt' ];
        
    }

    try {
        const applications = await Application.findAndCountAll({
            include: [
                {                               
                    model: Job,
                    include: [ 
                        { 
                            model: Company,
                            attributes: [ 'id', 'name' ],
                            include: [
                                {
                                    model: Person,
                                    attributes: [ 'firstName', 'lastName', 'phone', 'email' ]
                                }
                            ]
                        } 
                    ]
                },
                {
                    model: Applicant,
                    include: [ 
                        {
                            model: Person,
                            attributes: [ 'id', 'firstName', 'lastName', 'email', 'phone', 'createdAt' ]
                        } 
                    ],
                }
            ],

            subQuery: false,

            order: orderFields,      
            limit: parseInt(limit, 10), 
            offset: parseInt(index),
            distinct: true,
            attributes: [ 
                'id',
                'applicantId',
                'jobId',
                [Sequelize.fn('date_format', Sequelize.col('application.createdAt' ), '%d/%m/%y'), 'applicationDate']
 
            ]
        });
        console.log(applications.rows.length); // 7  -- wrong
        console.log(limit);                    // 12 -- correct
        res.status(200).json({msg: 'success', applications: applications});

    } catch (err) {
        console.log(err);
    }

Associations:协会:

Company.hasMany(Job, { foreignKey: { name: 'companyId', allowNull: false} });
Job.belongsTo(Company, { foreignKey: { name: 'companyId', allowNull: false} });

Person.hasOne(Applicant, { foreignKey: { name: 'personId', allowNull: false, unique: true } });
Applicant.belongsTo(Person, { foreignKey: { name: 'personId', allowNull: false, unique: true } });

Applicant.belongsToMany(Job, { through: Application });
Job.belongsToMany(Applicant, { through: Application });
// Set associations so the Application table can be queried directly
Application.belongsTo(Job, { foreignKey: { name: 'jobId' }});
Application.belongsTo(Applicant, { foreignKey: { name: 'applicantId' } });

Person.belongsToMany(Company, { through: Contact });
Company.belongsToMany(Person, { through: Contact });

In order to properly use findAndCountAll you need to get rid of many-to-many in include option OR convert it to one-to-many and use separate: true option.为了正确使用findAndCountAll ,您需要摆脱include选项many-to-many或将其转换one-to-many并使用separate: true选项。

associations协会

Company.hasMany(Contact, { foreginKey: 'companyId' });
Contact.belongsTo(Person, { foreginKey: 'personId' });

possible include option可能包括选项

{ 
  model: Company,
  attributes: [ 'id', 'name' ],
  include: [
    {
      model: Contact,
      separate: true,
      attributes: [],
      include: [{
        model: Person,
        attributes: [ 'firstName', 'lastName', 'phone', 'email' ]
      }]
    }
  ]
}

And yes, you will get an extra level to get person attributes through Contact .是的,您将获得额外的级别以通过Contact获取人员属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM