【问题标题】:create/update with Many to Many association in Node.js sequelize and PostgreSQL在 Node.js sequelize 和 PostgreSQL 中使用多对多关联创建/更新
【发布时间】:2020-03-03 06:38:42
【问题描述】:

我只是在创建或更新一个与另一个表具有多对多关联的表,如下所示: 公司 行业 CompanyIndustryRelation。

Industry.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const Industry = sequelize.define('Industry', {
    industry_name: DataTypes.STRING,
  }, {
    timestamps: false,
    underscored: true,
    tableName: 'industry',
  });
  Industry.associate = function(models) {
    Industry.belongsToMany(models.Company, {
      through: 'company_industry_relation', foreignkey: 'industry_id'
    });
  };
  return Industry;
};

公司.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const Company = sequelize.define('Company', {
    company_name: DataTypes.STRING,
  }, {
    timestamps: false,
    underscored: true,
    tableName: 'company',
  });
  Company.associate = function(models) {
    Company.belongsToMany(models.Industry, {
      through: 'company_industry_relation', foreignKey: 'company_id'
    });
  };
  return Company;
};

CompanyIndustryRelation.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const CompanyIndustryRelation = sequelize.define('CompanyIndustryRelation', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
    },
  }, {
    timestamps: false,
    underscored: true,
    tableName: 'company_industry_relation',
  });
  return CompanyIndustryRelation;
};

目前我已经建立了如下所示的行业表。

行业阵列 行业 = [ {标签:'会计'},{标签:'计算机科学'}]

公司名称:'ApolloIT'

我想使用给定的行业数组和公司名称创建新的公司记录。

提前致谢!

【问题讨论】:

  • 您的问题不清楚。请更具体。如果您展示一个数据示例以及您想要实现的目标,那就更好了。与你的关系我只能看到Company -> CompanyIndustryRelation <- Industry。不清楚您要创建或更新什么。
  • 丹,感谢您的回复!刚刚更新了问题。
  • 丹,我试过这样for (const i of industry) { const industryInstance = await Industry.findOne({ industry_name: i.label }); await CompanyIndustryRelation.create({ company_id: company.id, industry_id: industryInstance.id }); } 但它说错误"id" of relation "company_industry_relation" does not exist

标签: sql node.js postgresql sequelize.js


【解决方案1】:

我找到了一种通过关联创建/更新记录的简单方法。

industries: [ 
 { value: 'Gaming', label: 'Gaming' },
 { value: 'Computer Science', label: 'Computer Science' } 
]

const company = await Company.create({
   company_name: companyName,
});

const industry = await Industry.findAll({
   where: { industry_name: { [Op.in]: _.map(industries, o => o.label) } }
});
await company.addIndustry(industry);

请参考这里。 https://sequelize.org/master/manual/advanced-many-to-many.html

【讨论】:

    【解决方案2】:

    好的。据我所知,您的模型定义不正确。在 sequelize 中,您创建一个与数据库表相关的模型,通常,此模型必须与数据库表相同。

    对于 Industry.js,您只需定义行业名称列,忘记 id。 Company.js 也是如此。如果 sequeliaze 不知道主键......它不会很好地工作。

    对于 CompanyIndustryRelation.js,通常不需要 id,因为主键(通常)是相关表的 id。在这种情况下,它应该是industry_idcompany_id。同样,在 CompanyIndustryRelation.js 中没有这样的字段。

    当您使用n to n 关系时,首先您需要创建主表。如果你有:

    公司 ---> CompanyIndustryRelation

    那么首先你必须创建companyindustry 然后CompanyIndustryRelation

    在 sequelize 中你可以做(​​创建):

    sequelize.transaction((t) => {// to make a rollback in case something goes wrong
    
        return Company.create(data_company, { transaction: t }).then((new_company) => {
    
            return Industry.create(data_industry, { transaction: t }).then((new_industry) => {
    
                //here goes the created ids, asuming your using autoincrement to create ids
                var data_relation = {industry_id: new_industry.id,company_id: new_company.id};
                return CompanyIndustryRelation.create(data_relation, { transaction: t }).then(()=>{
    
                    return;// Everything OK you could return something here
    
    // when there is an error, you have to throw it for the rollback to work
                }).catch(err => {throw err;});
    
            }).catch(err => {throw err;});
    
        }).catch(err => {throw err;});
    
    }).catch(err => {
        // process error, then rollback
    });
    

    对于更新,如果你想级联更新也是一样的,最好使用事务,以防中间出现问题。

    还有其他方法可以使用级联更新或创建,但如果您使用transactions,一切都会更好

    【讨论】:

    • 谢谢你的回答,顺便说一句。有什么方法可以使用 async-await 吗?并且交易的使用是必须的和强制性的?
    • 链接中的transactions是sequelize手册以及如何与await一起使用。
    • TypeError: _sequelize.default.transaction 不是函数,在哪里可以引用 sequelize?
    • 可惜没用,还在说column "id" of relation "company_industry_relation" does not exist
    • 我试过const t = await db.sequelize.transaction(); const company = await Company.create({ company_name: companyName }, { transaction: t }); for (const industry of industries) { const industryInstance = await Industry.findOne({ industry_name: industry.label }); await CompanyIndustryRelation.create({ company_id: company.id, industry_id: industryInstance.id }, { transaction: t }); await t.commit(); }但是不行
    猜你喜欢
    • 1970-01-01
    • 2016-08-24
    • 2016-12-09
    • 2020-08-12
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    相关资源
    最近更新 更多