簡體   English   中英

sequelize 中的多對一關聯

[英]Many to one association in sequelize

我有兩個表表 1 (D) 和表 2 (P)

表 1 的每一行可以有一個或多個從表 2(P) 映射的行

例如:D1 -> P1,P2,P3 D2 -> P1,P3

如何在 sequelize 中實現從表 1 到表 2 的多對一關聯。請幫助。

我在讓 Sequelize 也能正常工作時遇到了很多麻煩。 這是我的做法。
假設您使用 sequelize-cli: https://www.npmjs.com/package/sequelize-cli

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

這使我們的項目接下來使用遷移來啟動我們的 D 和 P 表以及 D 和 P 模型。

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

生成器所能做的就是為表命名、聲明變量並賦予它們類型。 接下來我們編輯 D 和 P 遷移文件以匹配我們想要的表。 我們還配置我們的數據庫連接。 看到遷移文件后,編輯遷移文件非常直觀。 這是我制作的文件。

//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');
  }
};

甚至在編輯 Create P 和 Create D 之前運行 npx sequelize-cli db:migrate 來測試您的連接。 當連接正常並且您獲得表時,然后繼續運行 migrate 以測試您對 Create P 和 Create D 的更改。只需刪除所有表並再次運行 migrate。 第一個技巧是將適當的外鍵添加到遷移文件中。 這是P.Did。 參考選項很重要。 我認為遷移文件創建了所有的數據庫結構。 接下來我們調整model文件; 注釋在代碼中:

//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;
};

技巧 2 或技巧 1 的第二部分是將外鍵選項添加到 D.hasmany 和 P.belongsto。 這避免了許多陷阱。
最后是一些測試代碼:

//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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM