如何在sequelize中返回非唯一的连接表记录?

时间:2018-03-20 23:52:13

标签: javascript mysql node.js postgresql sequelize.js

我询问一个特定的学生,包括多对多公司的关系,但是对于同一studentId和companyId的记录,他们并没有回来。连接表也有一个带有id的主键。

查看我包含属于belongsToMany关系的公司的行

独特,约束并没有做太多尝试,但偏执的工作。我当时能够获取deletedAt记录。

export function getStudent(req, res, next) {
  Students.find({
    where: {
      id: req.params.id
    },
    order: [
      [{model: Addresses}, 'id', 'DESC'],
      [{model: Companies}, 'id', 'DESC'],
    ],
    include: [{model: Schools},
              {model: ClassificationTypes},
              {model: Companies,
                as: 'Companies',
                paranoid: false,
                through: { paranoid: false, unique: false, constraints: false }
              },
              {model: Drivers,
                as: 'Drivers'},
              {model: Addresses,
                as: 'Addresses',
                through: { paranoid: false },
                include: [{model: AddressTypes},
                          {model: States,
                          paranoid: false }]
              }
            ]
  }).then((students) => {
    return res.json(students);
  }).catch((err) => {
    res.sendStatus(500);
    next(err);
  });
}


Here are my models: 


export default (sequelize, DataTypes) => {
  const CompaniesStudents = sequelize.define('CompaniesStudents', {
    companyId: DataTypes.INTEGER,
    studentId: DataTypes.INTEGER,
    extraFees: DataTypes.FLOAT,
    createdAt: {
        type: DataTypes.DATE
    },
    updatedAt: {
        type: DataTypes.DATE
    },
    deletedAt: {
        type: DataTypes.DATE
    }
  }, {
    timestamps: true,
    paranoid: true,
  }
);
  return CompaniesStudents;
};
```
```js
export default (sequelize, DataTypes) => {
  const Companies = sequelize.define('Companies', {
    name: DataTypes.STRING,
    description: DataTypes.STRING,
    phone: DataTypes.STRING,
    email: DataTypes.STRING,
    createdAt: {
        allowNull: false,
        type: DataTypes.DATE
    },
    updatedAt: {
        allowNull: false,
        type: DataTypes.DATE
    },
    deletedAt: {
        type: DataTypes.DATE
    }
  }, {
    timestamps: true,
    paranoid: true,
  }
);

  Companies.associate = (models) => {
    Companies.belongsToMany(models.Drivers, {through: 'CompaniesDrivers', as: 'Drivers', foreignKey: 'companyId', otherKey: 'driverId'});
    Companies.belongsToMany(models.Students, {through: 'CompaniesStudents', as: 'Students', foreignKey: 'companyId', otherKey: 'studentId'});
    Companies.belongsToMany(models.Zones, {through: 'CompaniesZones', as: 'Zones', foreignKey: 'companyId', otherKey: 'zoneId'});
    Companies.belongsToMany(models.User, {through: 'CompaniesUsers', as: 'Users', foreignKey: 'companyId', otherKey: 'userId'});
    Companies.belongsToMany(models.Addresses, {through: 'CompaniesAddresses', as: 'Addresses', foreignKey: 'companyId', otherKey: 'addressId'});
  };

  return Companies;
};



export default (sequelize, DataTypes) => {
  const Students = sequelize.define('Students', {
    studentIdentification: DataTypes.INTEGER,
    firstName: DataTypes.STRING,
    lastName: DataTypes.STRING,
    schoolId: {
      type: DataTypes.INTEGER,
        references: {
          model: 'Schools',
          key: 'id'
        }
    },
    classificationTypeId: {
      type: DataTypes.INTEGER,
          references: {
            model: 'ClassificationTypes',
            key: 'id',
          }
      },
    zoneId: {
      type: DataTypes.INTEGER,
        references: {
          model: 'Zones',
          key: 'id'
        }
    },
    desiredPickUpTime: DataTypes.DATE,
    desiredDropOffTime: DataTypes.DATE,
    createdAt: {
        allowNull: false,
        type: DataTypes.DATE
    },
    updatedAt: {
        allowNull: false,
        type: DataTypes.DATE
    },
    deletedAt: {
        type: DataTypes.DATE
    }
  }, {
    timestamps: true,
    paranoid: true,
  }
);
  Students.associate = (models) => {
    Students.belongsTo(models.ClassificationTypes, { foreignKey: 'classificationTypeId'});
    Students.belongsTo(models.Schools, {foreignKey: 'schoolId'});
    Students.belongsTo(models.Zones, {foreignKey: 'zoneId'});
    Students.belongsToMany(models.Companies, {through: 'CompaniesStudents', as: 'Companies', foreignKey: 'studentId', otherKey: 'companyId'});
    Students.belongsToMany(models.Drivers, {through: 'DriversStudents', as: 'Drivers', foreignKey: 'studentId', otherKey: 'driverId'});
    Students.belongsToMany(models.Addresses, {through: 'StudentsAddresses', as: 'Addresses', foreignKey: 'studentId', otherKey: 'addressId'});
  };

  return Students;
};

我希望所有记录都返回,无论它们是否被软删除。

仅返回与其相关的最后一条记录

以下是学生所属的两家公司的例子 以下是记录: image

"Companies": [
        {
            "id": 19,
            "name": "Suspect Icecream truck",
            "description": "",
            "phone": "21312314",
            "email": "koawewa",
            "createdAt": "2018-03-20T19:41:03.578Z",
            "updatedAt": "2018-03-20T19:41:16.500Z",
            "deletedAt": null,
            "CompaniesStudents": {
                "companyId": 19,
                "studentId": 6,
                "extraFees": null,
                "createdAt": "2018-03-20T20:05:03.239Z",
                "updatedAt": "2018-03-20T20:05:03.239Z",
                "deletedAt": null
            }
        },
        {
            "id": 18,
            "name": "Karans Pickup Company",
            "description": "",
            "phone": "917321312",
            "email": "a21@yasd.com",
            "createdAt": "2018-03-20T19:40:39.012Z",
            "updatedAt": "2018-03-20T19:40:54.042Z",
            "deletedAt": null,
            "CompaniesStudents": {
                "companyId": 18,
                "studentId": 6,
                "extraFees": null,
                "createdAt": "2018-03-20T19:42:50.399Z",
                "updatedAt": "2018-03-20T19:42:50.399Z",
                "deletedAt": "2018-03-20T19:43:02.784Z"
            }
        }
    ],

2 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

我意识到这个问题已经存在了2年之久,但是最近我偶然发现了这个问题,我想分享我找到的解决方案。

问题在于,从v6.3.5开始,Sequelize在使用BelongToMany关联时仍不直接支持通过表重复的条目。

问题已经raised,并且从那里我有了解决方案的想法。

基本上,您想要做的是将您的M:N关系替换为两个1:N。在Sequelize中,这意味着您无需声明A.belongsToMany(B, {through: 'C'})之类的关系,而是声明A.hasMany(C)C.belongsTo(A)B.hasMany(C)C.belongsTo(B)。当然,这还需要显式声明C模型,而不是由BelongsToMany关系自动声明它。这实际上在续集documentation中得到了暗示。

根据您的情况,对于您的BelongsToMany关系之一,则为:

公司模型(A)

export default (sequelize, DataTypes) => {
  const Companies = sequelize.define('Companies', {
    name: DataTypes.STRING,
    description: DataTypes.STRING,
    phone: DataTypes.STRING,
    email: DataTypes.STRING,
  }, {
    timestamps: true,
    paranoid: true,
  }
);

  Companies.associate = (models) => {
    Companies.hasMany(models.CompaniesStudents, {foreignKey: 'companyId');
  };

  return Companies;
};

学生模型(B)

export default (sequelize, DataTypes) => {
  const Students = sequelize.define('Students', {
    studentIdentification: DataTypes.INTEGER,
    firstName: DataTypes.STRING,
    lastName: DataTypes.STRING,
    desiredPickUpTime: DataTypes.DATE,
    desiredDropOffTime: DataTypes.DATE,
  }, {
    timestamps: true,
    paranoid: true,
  }
);

  Students.associate = (models) => {
    Students.hasMany(models.CompaniesStudents, {foreignKey: 'studentId'});
  };

  return Students;
};

通过表格模型(C)

export default (sequelize, DataTypes) => {
  const CompaniesStudents = sequelize.define('CompaniesStudents', {
    companyId: DataTypes.INTEGER,
    studentId: DataTypes.INTEGER,
    extraFees: DataTypes.FLOAT,
  }, {
    timestamps: true,
    paranoid: true,
  }
);

  CompaniesStudents.associate = (models) => {
    CompaniesStudents.belongsTo(models.Companies, {foreignKey: 'companyId'});
    CompaniesStudents.belongsTo(models.Students, {foreignKey: 'studentId'});
  };

  return CompaniesStudents;
};

这样,要在查询学生时获取关联公司的列表(包括“重复的”条目),您的查询将是:

Students.findAll({
  include: [{
    model: CompaniesStudents, 
    include: Companies
  }]
});

将以以下形式返回元素

{
  'id': 1,
  'CompaniesStudents': [
    {
      'companyId': 20,
      'studentId': 1,
      'extraFees': 100,
      'Companies': {'id': 20}
    }, {
      'companyId': 20,
      'studentId': 1,
      'extraFees': 200,
      'Companies': {'id': 20}
    }
  ]
}

当然,您将必须为所有其他关系添加对应的关联,以及通过表的显式模型。