属于许多关联,将外键添加到源模型,SequelizeDatabaseError:列“ CategoryID”不存在

问题描述 投票:0回答:1

我试图解释我的情况。我有两个模型:FilmCategory。他们是N:M协会。

迁移文件20200123070411-createTables.js

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('Category', {
      ID: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false,
      },
      Name: {
        type: Sequelize.STRING(20),
        allowNull: false,
      },
      Last_Update: {
        type: Sequelize.DATE,
        allowNull: false,
      },
    });
    await queryInterface.createTable('Language', {
      ID: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false,
      },
      Name: {
        type: Sequelize.STRING(20),
        allowNull: false,
      },
      Last_Update: {
        type: Sequelize.DATE,
        allowNull: false,
      },
    });
    await queryInterface.createTable('Film', {
      ID: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false,
      },
      LanguageID: {
        type: Sequelize.INTEGER,
        references: {
          model: 'Language',
          key: 'ID',
        },
        onDelete: 'restrict',
        allowNull: false,
      },
      Title: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      Description: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      Release_Year: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      Rental_Duration: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      Rental_Date: {
        type: Sequelize.DECIMAL(19, 0),
        allowNull: false,
      },
      Length: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      Replacement_Cost: {
        type: Sequelize.DECIMAL(19, 0),
        allowNull: false,
      },
      Rating: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      Last_Update: {
        type: Sequelize.DATE,
        allowNull: false,
      },
      Special_Features: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      Fulltext: {
        type: Sequelize.STRING,
        allowNull: false,
      },
    });

    await queryInterface.createTable(
      'Film_Category',
      {
        FilmID: {
          type: Sequelize.INTEGER,
          // composite primary key
          primaryKey: true,
          references: {
            model: 'Film',
            key: 'ID',
          },
          onDelete: 'restrict',
        },
        CategoryID: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          references: {
            model: 'Category',
            key: 'ID',
          },
          onDelete: 'cascade',
        },
        Last_Update: {
          type: Sequelize.DATE,
          allowNull: false,
        },
      }
    );
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('Film_Category');
    await queryInterface.dropTable('Film');
    await queryInterface.dropTable('Category');
    await queryInterface.dropTable('Language');
  },
};

执行数据库迁移后,我在下面定义模型:

models/category.ts

import { Model, DataTypes, BelongsToManyGetAssociationsMixin } from 'sequelize';
import { sequelize } from '../db';
import { Film } from './film_category';

class Category extends Model {
  public ID!: number;
  public Name!: string;
  public Last_Update!: Date;
  public getFilms!: BelongsToManyGetAssociationsMixin<Film>;
}
Category.init(
  {
    ID: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
      allowNull: false,
    },
    Name: {
      type: DataTypes.STRING(20),
      allowNull: false,
    },
    Last_Update: {
      type: DataTypes.DATE,
      allowNull: false,
    },
  },
  { sequelize, modelName: 'Category' },
);

export { Category };

models/film.ts

import { Model, DataTypes, BelongsToManyGetAssociationsMixin } from 'sequelize';
import { sequelize } from '../db';
import { Category } from './film_category';

class Film extends Model {
  public ID!: number;
  public LanguageID!: number;
  public Title!: string;
  public Description!: string;
  public Release_Year!: number;
  public Rental_Duration!: number;
  public Rental_Date!: number;
  public Length!: number;
  public Replacement_Cost!: number;
  public Rating!: number;
  public Last_Update!: Date;
  public Special_Features!: string;
  public Fulltext!: string;
  public getCategories!: BelongsToManyGetAssociationsMixin<Category>;
}
Film.init(
  {
    ID: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
      allowNull: false,
    },
    LanguageID: {
      type: DataTypes.INTEGER,
      references: {
        model: 'Language',
        key: 'ID',
      },
      onDelete: 'restrict',
      allowNull: false,
    },
    Title: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    Description: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    Release_Year: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    Rental_Duration: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    Rental_Date: {
      type: DataTypes.DECIMAL(19, 0),
      allowNull: false,
    },
    Length: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    Replacement_Cost: {
      type: DataTypes.DECIMAL(19, 0),
      allowNull: false,
    },
    Rating: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    Last_Update: {
      type: DataTypes.DATE,
      allowNull: false,
    },
    Special_Features: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    Fulltext: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  { sequelize, modelName: 'Film' },
);

export { Film };

models/film_category.ts

import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../db';
import { Category } from './category';
import { Film } from './film';

class FilmCategory extends Model {
  public FilmID!: number;
  public CategoryID!: number;
  public Last_Update!: Date;
}
FilmCategory.init(
  {
    FilmID: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      references: {
        model: 'Film',
        key: 'ID',
      },
      onDelete: 'restrict',
    },
    CategoryID: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      references: {
        model: 'Category',
        key: 'ID',
      },
      onDelete: 'cascade',
    },
    Last_Update: {
      type: DataTypes.DATE,
      allowNull: false,
    },
  },
  { sequelize, modelName: 'Film_Category' },
);

export { FilmCategory, Film, Category };

models/index.ts

import { Category } from './category';
import { Film } from './film';
import { Language } from './language';
import { FilmCategory } from './film_category';

Category.belongsToMany(Film, { through: FilmCategory });
Film.belongsToMany(Category, { through: FilmCategory });

Language.hasMany(Film);

export { Category, Film, Language, FilmCategory };

[当我尝试呼叫Film.findByPk(1)时,sequelize引发错误:

SequelizeDatabaseError:列“ CategoryID”不存在

sequelizeFilm.findByPk(1)生成的SQL查询是这样的:

执行(默认):SELECT“ ID”,“ LanguageID”,“ Title”,“ Description”,“ Release_Year”,“ Rental_Duration”,“ Rental_Date”,“ Length”,“ Replacement_Cost”,“ Rating”,“ Last_Update” “,” Special_Features“,”全文“,”类别ID“从”电影“作为”电影“,在”电影“。” ID“ = 1;

[我知道当我使用Film.belongsToMany(Category, { through: FilmCategory });时,sequelize会将目标模型CategoryIDCategory添加到源模型Film。我希望通过主键找到的影片数据具有与模型模式相同的属性。这是额外的CategoryID列。

因此,我不希望在CategoryID模型上添加Film列,而在FilmID模型上添加Category列。因为Film表在数据库中没有CategoryID列,并且Category表没有在数据库中FilmID列。它们通过连接表Film_Category连接。有什么办法吗?还是我错过了什么?

创建了一个最小的可复制代码仓库:https://github.com/mrdulin/node-sequelize-examples/tree/master/src/db

node.js postgresql typescript sequelize.js
1个回答
0
投票

如果您在关联中显式定义“通过”表,则应该起作用,如下所示:

    Film.belongsToMany(Category, 
        {
         through: FilmCategory, 
         foreignKey: 'FilmID',  
         otherKey: 'CategoryID' 
        });

很可能会出现问题,因为您使用的是ID而不是ID,但这只是猜测...

HTH

© www.soinside.com 2019 - 2024. All rights reserved.