javascript - Sequelizejs belongsToMany 与 otherKey 的关系

标签 javascript node.js sequelize.js

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

Song 有很多 Artists,Artist 有很多 Songs,这是一个多对多的关系,所以我定义了一个连接表 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;
};

默认行为是 SongArtist 使用 SongsArtists 主键('id')来查询,但我想使用 Songs 和 Artists 中的 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;
};

艺术家模型:

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

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

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

> SequelizeDatabaseError: column Artists.SongArtist.neteaseId does not exist

那么如何在多对多查询中更改默认查询列,并且应该生成以下 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"

代替

LEFT OUTER JOIN ("SongArtist" AS "Artists.SongArtist"
INNER JOIN "Artists" AS "Artists" ON "Artists"."id" =   "Artists.SongArtist"."artistId") 
ON "Songs"."id" = "Artists.SongArtist"."songId"

最佳答案

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

的文档

The name of the foreign key in the join table (representing the target model) or an object representing the type definition for the other column (see Sequelize.define for syntax). When using an object, you can add a name property to set the name of the column. Defaults to the name of target + primary key of target

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

const sourceKey = this.source.rawAttributes[this.source.primaryKeyAttribute];

this.source 是您的源模型,所以不是 SongArtist。如您所见,它会自动选择此模型的 primaryKeyAttribute,在这两种情况下都是 id 字段。 github 上什至存在与您遇到的相同问题有关的问题,答案是在这种情况下只能接受主键字段 - Specify non-primary target key in belongsToMany association

关于javascript - Sequelizejs belongsToMany 与 otherKey 的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42610767/

相关文章:

mysql - My SQL 数据库 Sequelize npm

javascript - Sequelize – 查询重叠日期但有异常

javascript - 如何在第二次单击时反转 javascript 中的函数?

Javascript 异步调用相互踩踏

javascript - Meteor 301重定向nodejs

javascript - 在某些日期失败的时刻

javascript - Kendo UI 网格 - 过滤器 - 日期范围

javascript - 库使用 localStorage - Chrome 网上应用店

node.js - 如何通过隧道将 NodeJS 调试器连接到 Vagrant 盒子?

node.js - 通过 Sequelize 连接表嵌套关联数据