简体   繁体   中英

Many to one association in sequelize

I have two tables Table 1 (D) and Table 2 (P)

Each row of Table 1 can have one or many rows mapped from Table 2(P)

Eg: D1 -> P1,P2,P3 D2 -> P1,P3

How can I achieve many-to-one association from Table 1 to Table 2 in sequelize.Please help.

I've had a lot of trouble getting Sequelize to work as well. Here is how I do it.
Assuming you use the sequelize-cli: https://www.npmjs.com/package/sequelize-cli :

npm install --save-dev sequelize-cli
npx sequelize-cli init

this gives us our project next use migrations to jumpstart our D and P tables and D and P models.

npx sequelize-cli model:generate --name D --attributes firstVariable:string,secondVariable:string,thirdVariable:string
// i made p the same way

About all the generator can do is name the table, declare the variables, and give them types. Next we edit the D and P migration files to match the tables we want. We also configure our database connection. Editing the migration files is intuitive once you see them. Here are the files I made.

//simple as you can get changes to config.json to
{
  "development": {
    "storage" : "/wherever/im/putting/mydatabase.db",
    "dialect": "sqlite"
  }
}

//create d
'use strict';
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('D', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      firstVariable: {
        type: Sequelize.STRING
      },
      secondVariable: {
        type: Sequelize.STRING
      },
      anotherVariable: {
        type: Sequelize.STRING
      }//,
      // createdAt: {
      //   allowNull: false,
      //   type: Sequelize.DATE
      // },
      // updatedAt: {
      //   allowNull: false,
      //   type: Sequelize.DATE
      // }
    });
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('D');
  }
};

//create P
'use strict';
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('P', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      firstVariable: {
        type: Sequelize.STRING
      },
      secondVariable: {
        type: Sequelize.STRING
      },
      anotherVariable: {
        type: Sequelize.STRING
      },
      Did: {
        type: Sequelize.INTEGER, 
        references: {
          model: 'D',
          key: 'id'
        }
       }//,
      // createdAt: {
      //   allowNull: false,
      //   type: Sequelize.DATE
      // },
      // updatedAt: {
      //   allowNull: false,
      //   type: Sequelize.DATE
      // }
    });
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('P');
  }
};

before even editing Create P and Create D run npx sequelize-cli db:migrate to test your connection. When the connection works and you get tables, Then keep running migrate to test your changes to Create P and Create D. Just delete all the tables and run migrate again. The first trick is to add the appropriate foreign keys to the migration files. Here that is P.Did. The references option is important. I think of the migration files as creating all of the database structure. Next we adjust the model files; comments are in the code:

//D.js
'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class D extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      D.hasMany(models.P, {foreignKey: "Did", onDelete: 'CASCADE', onUpdate: 'CASCADE'}); // https://sequelize.org/master/manual/assocs.html
    }
  };
  D.init({
    firstVariable: DataTypes.STRING,
    secondVariable: DataTypes.STRING,
    anotherVariable: DataTypes.STRING
  }, {
    sequelize,
    timestamps: false, //timestamps may need to be first option?
    modelName: 'D',
    tableName: 'D'
  });
  return D;
};

//P.js
'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class P extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      P.belongsTo(models.D, {onDelete: 'CASCADE', onUpdate: 'CASCADE', foreignKey: 'Did'}); //not setting onUpdate and onDelete, if also doesn't work on your system set in database instead
     
    }
  };
  P.init({ //I make sure all P variables are in init, but I have not test if adding the foreign key is necessary here
    firstVariable: DataTypes.STRING,
    secondVariable: DataTypes.STRING,
    anotherVariable: DataTypes.STRING,
    Did: DataTypes.INTEGER 
  }, {
    sequelize,
    timestamps: false, //otherwise sequelize assumes timestamps are in the table and writes queries accordingly
    modelName: 'P',
    tableName: 'P'
  });
  return P;
};

Trick 2 or the second part of trick 1 is adding the foreign key option to D.hasmany and P.belongsto. This avoids many pitfalls.
Finally here is some code for testing:

//index.js
//index.js to test code
const db = require('./models');
const asyncouterFunction = async function() {
const D = db.D;
const P = db.P;
const d1 = await D.create({firstVariable: "A", secondVariable:"B", anotherVariable: "C"});
const p1 = await P.create({firstVariable: "a", secondVariable:"b", anotherVariable: "c"});
const p2 = await P.create({firstVariable: "a", secondVariable:"b", anotherVariable: "c"});
await d1.addPs([p1,p2]);
let count = await d1.countPs();
console.log(count);
await d1.removeP(p2);
count = await d1.countPs();
console.log(count)
}
asyncouterFunction();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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