Sequelize.js与otherKey的TotalToMany关系

Tan*_*onk 4 node.js sequelize.js

我正在创建有关歌曲和艺术家的应用程序,以下是数据库架构:

歌曲有很多艺术家,而艺术家有很多歌曲,这是多对多的关系,所以我定义了一个联接表SongArtist

SongArtist模型:

module.exports = function(sequelize, DataTypes) {
  var SongArtist = sequelize.define('SongArtist', {
    id: {
      type: DataTypes.INTEGER,
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    songId: {
      type: DataTypes.INTEGER,
      allowNull: false,

    },
    artistId: {
      type: DataTypes.INTEGER,
      allowNull: false,

    }
  }, {
    tableName: 'SongArtist',
  });
  return SongArtist;
};
Run Code Online (Sandbox Code Playgroud)

默认行为是SongArtist使用查询SongsArtists主键('id')进行查询,但是我想使用neteaseId“歌曲和艺术家”中的列进行多对多查询,因此我otherKey在以下方法中使用:

歌曲型号:

module.exports = function(sequelize, DataTypes) {
  var Songs = sequelize.define('Songs', {
    id: {
      type: DataTypes.INTEGER,
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: true
    },
    neteaseId: {
      type: DataTypes.INTEGER,
      allowNull: false,
      unque: true
    }
  }, {
    tableName: 'Songs',
    classMethods: {
      associate: (models) => {
        Songs.belongsToMany(models.Artists,{
          through: 'SongArtist',
          foreignKey: 'songId',
          otherKey: 'neteaseId'
        })
      }
    }
  });

  return Songs;
};
Run Code Online (Sandbox Code Playgroud)

艺术家模型:

module.exports = function(sequelize, DataTypes) {
  var Artists = sequelize.define('Artists', {
    id: {
      type: DataTypes.INTEGER,
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING,
      allowNull: true
    },
    neteaseId: {
      type: DataTypes.INTEGER,
      allowNull: false,
      unque: true
    }
  }, {
    tableName: 'Artists',
    classMethods: {
      associate: (models) => {
        Artists.belongsToMany(models.Songs,{
          through: 'SongArtist',
          foreignKey: 'artistId',
          otherKey: 'neteaseId'
        })
      }
    }
  });

  return Artists;
};
Run Code Online (Sandbox Code Playgroud)

但是,当我使用以下代码执行查询时,会向我抛出错误:

models.Songs.findAll({include: [models.Artists, models.Album]})

> SequelizeDatabaseError: column Artists.SongArtist.neteaseId does not exist
Run Code Online (Sandbox Code Playgroud)

因此,如何在多对多查询中更改默认查询列,并应生成以下sql:

LEFT OUTER JOIN ("SongArtist" AS "Artists.SongArtist"
INNER JOIN "Artists" AS "Artists" ON "Artists"."neteaseId" =    "Artists.SongArtist"."artistId") 
ON "Songs"."id" = "Artists.songId"."songId"
Run Code Online (Sandbox Code Playgroud)

代替

LEFT OUTER JOIN ("SongArtist" AS "Artists.SongArtist"
INNER JOIN "Artists" AS "Artists" ON "Artists"."id" =   "Artists.SongArtist"."artistId") 
ON "Songs"."id" = "Artists.SongArtist"."songId"
Run Code Online (Sandbox Code Playgroud)

pio*_*ias 5

otherKey您使用的选项不是用于选择关联中使用的源模型的字段。根据文档otherKey

联接表中的外键名称(代表目标模型)或代表另一列的类型定义的对象(有关语法,请参见Sequelize.define)。使用对象时,可以添加名称属性来设置列的名称。默认为目标名称+目标主键

它在连接表中为目标模型指定外键,因此它是连接表中的列,而不是源/目标表中的列。而且,根据Sequelize的源代码,belongsToMany在这种关联中不可能使用除主键以外的其他字段。下面的代码行从源模型中选择字段

const sourceKey = this.source.rawAttributes[this.source.primaryKeyAttribute];
Run Code Online (Sandbox Code Playgroud)

哪里this.source是你的源模型,以便相当SongArtist。如您所见,它会自动选择primaryKeyAttribute此模型的,在两种情况下均为idfield。github上甚至存在一个与您遇到的相同问题有关的问题,答案说,在这种情况下,仅主键字段是可接受的- 在belongsToMany关联中指定非主目标键