Javascript Sequelizejs与otherKey之间的关系
我正在创建一个关于歌曲和艺术家的应用程序,以下是数据库模式: 歌曲有很多艺术家,艺术家有很多歌曲,这是一个多对多的关系,所以我定义了一个联接表Javascript Sequelizejs与otherKey之间的关系,javascript,node.js,sequelize.js,Javascript,Node.js,Sequelize.js,我正在创建一个关于歌曲和艺术家的应用程序,以下是数据库模式: 歌曲有很多艺术家,艺术家有很多歌曲,这是一个多对多的关系,所以我定义了一个联接表songaister: 歌手模型: module.exports = function(sequelize, DataTypes) { var SongArtist = sequelize.define('SongArtist', { id: { type: DataTypes.INTEGER, allowNull: f
songaister
:
歌手模型:
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;
};
默认行为是使用SongArtister
和Artisters
主键('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;
};
艺术家模型:
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
联接表中外键的名称(表示目标模型)或表示另一列类型定义的对象的名称(有关语法,请参阅Sequelize.define)。使用对象时,可以添加name属性来设置列的名称。默认为目标的名称+目标的主键
它在目标模型的联接表中指定外键,因此它是联接表中的一列,而不是源/目标表中的一列。而且,根据Sequelize的源代码,在这种关联中不可能使用主键以外的字段。下面是一行从源模型中选择字段的代码
const sourceKey = this.source.rawAttributes[this.source.primaryKeyAttribute];
其中this.source
是您的源代码模型,而不是Song
或Artist
。如您所见,它会自动选择此模型的primaryKeyAttribute
,在这两种情况下都是id
字段。
github上甚至存在一个与您遇到的相同问题有关的问题,答案是,在这种情况下,只有主键字段是可接受的-支持
targetKey
和sourceKey
,在Sequelize中添加了多对多关系,如中所述
这里引用
有四种情况需要考虑:
我们可能希望使用默认的主节点建立多对多关系
Foo和Bar的键:
Foo.belongsToMany(Bar, { through: 'foo_bar' }); // This creates a junction table `foo_bar` with fields `fooId` and `barId`
Foo.belongsToMany(Bar, { through: 'foo_bar', sourceKey: 'name', targetKey: 'title' }); // This creates a junction table `foo_bar` with fields `fooName` and `barTitle`
对于Foo,我们可能希望使用默认主键>建立多对多关系,但对于Bar,则需要一个不同的字段:
Foo.belongsToMany(Bar, { through: 'foo_bar', targetKey: 'title' }); // This creates a junction table `foo_bar` with fields `fooId` and `barTitle`
我们可能希望使用不同的Foo字段和默认的Bar主键建立多对多关系:
Foo.belongsToMany(Bar, { through: 'foo_bar', sourceKey: 'name' }); // This creates a junction table `foo_bar` with fields `fooName` and `barId`
我们可能希望对Foo和Bar使用不同的字段建立多对多关系:
Foo.belongsToMany(Bar, { through: 'foo_bar' }); // This creates a junction table `foo_bar` with fields `fooId` and `barId`
Foo.belongsToMany(Bar, { through: 'foo_bar', sourceKey: 'name', targetKey: 'title' }); // This creates a junction table `foo_bar` with fields `fooName` and `barTitle`
代码示例如所示。粘贴在这里以供快速参考
const User = this.sequelize.define('User', {
id: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
field: 'user_id'
},
userSecondId: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
field: 'user_second_id'
}
}, {
tableName: 'tbl_user',
indexes: [
{
unique: true,
fields: ['user_second_id']
}
]
});
const Group = this.sequelize.define('Group', {
id: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
field: 'group_id'
},
groupSecondId: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
field: 'group_second_id'
}
}, {
tableName: 'tbl_group',
indexes: [
{
unique: true,
fields: ['group_second_id']
}
]
});
User.belongsToMany(Group, {
through: 'usergroups',
sourceKey: 'userSecondId'
});
Group.belongsToMany(User, {
through: 'usergroups',
sourceKey: 'groupSecondId'
});