【问题标题】:How to return non-unique join table records in sequelize?如何在sequelize中返回非唯一连接表记录?
【发布时间】:2018-08-29 23:04:30
【问题描述】:

我正在查询特定的“学生”,包括公司的多对多关系,但受骗者没有返回具有相同 studentId 和 companyId 的记录。连接表也有一个带有 id 的主键。

看看我包含 Companies 的那一行,它是一个 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;
};

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

只返回与之相关的最后一条记录

这是一个学生所属的两家不同公司的示例 以下是记录:

"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"
            }
        }
    ],

【问题讨论】:

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


    【解决方案1】:

    【讨论】:

    • 这令人困惑,我还没有尝试过,但唯一返回一个实例的是我的“学生”实例,而我的包含:[公司,地址]应该显示所有相关的数组实例。 find/findOne 是否仍然可以接受,因为它仅在 sql 查询中生成 select 1 from 'Students' where student id = :someId' 在外面。而它仍然会对其关联记录(公司、地址)进行内部左连接
    【解决方案2】:

    我知道这个问题已经有 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 关系自动声明它。这实际上在 Sequelize 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;
    };
    

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

    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}
        }
      ]
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      相关资源
      最近更新 更多