问题描述
我正在尝试为我的项目制作过滤歌曲,我有一系列从客户端获取的流派ID,我这样做是为了从一个ID中获取所有音频:
Audio.findAll({
include: [{
model: db.Genres,as: "genres",where: {
id: {
[Op.and]: [1]
}
},}]
})
但是我需要从各种流派/ mods id数组中获取所有音频,还希望通过流派ids和mods ids过滤音频,但是我不知道该怎么做,知道吗?
歌曲模型
const Audio = sequelize.define('Audio',{
id: {
autoIncrement: true,type: DataTypes.INTEGER(30),allowNull: false,primaryKey: true
},name: {
type: DataTypes.STRING(255),allowNull: false
},})
Audio.associate = function(models) {
Audio.belongsToMany(models.Genres,{through: 'AudioGenres',foreignKey: 'id_audio',as: 'genres'})
Audio.belongsToMany(models.Mods,{through: 'AudioMods',as: 'mods'})
}
AudioGenreModel
const AudioGenres = sequelize.define('AudioGenres',{
id_audio: {
type: DataTypes.INTEGER(11),primaryKey: true,references: {
model: 'Audio',key: 'id'
}
},id_genre: {
type: DataTypes.INTEGER(11),references: {
model: 'Genres',key: 'id'
}
})
AudioGenres.associate = function(models) {
AudioGenres.belongsTo(models.Audio,{foreignKey: 'id_audio'})
AudioGenres.belongsTo(models.Genres,{foreignKey: 'id_genre'})
};
AudioModModel
const AudioMods = sequelize.define('AudioMods',id_mod: {
type: DataTypes.INTEGER(11),references: {
model: 'Mods',key: 'id'
}
})
AudioMods.associate = function(models) {
AudioMods.belongsTo(models.Audio,{foreignKey: 'id_audio'})
AudioMods.belongsTo(models.Mods,{foreignKey: 'id_mod'})
};
Mods and Genres Model
const Mods = sequelize.define('Mods',})
Mods.associate = function(models) {
Mods.belongsToMany(models.Audio,foreignKey: 'id_mod',as: 'audios'})
}
const Genres = sequelize.define('Genres',})
Genres.associate = function(models) {
Genres.belongsToMany(models.Audio,foreignKey: 'id_genre',as: 'audios'})
}
解决方法
在查找值数组中的列时,应使用Op.in
查询运算符。定义中的许多字段都将使用关系自动创建,对于AudioGenres
和AudioMods
,您最初可以不使用任何字段来创建它们。
// only define name,others will be generated
const Audio = sequelize.define('Audio',{
name: {
type: DataTypes.STRING(255),allowNull: false
},});
Audio.associate = function(models) {
Audio.belongsToMany(models.Genres,{ as: 'genres',through: 'AudioGenres',foreignKey: 'id_audio' })
Audio.belongsToMany(models.Mods,{ as: 'mods',through: 'AudioMods',foreignKey: 'id_audio' })
}
const Genres = sequelize.define('Genres',});
Genres.associate = function(models) {
Genres.belongsToMany(models.Audio,{ as: 'audios',foreignKey: 'id_genre' })
}
const Mods = sequelize.define('mods',});
Mods.associate = function(models) {
Mods.belongsToMany(models.Audio,foreignKey: 'id_mod' })
}
// create empty table,relationships added automatically
const AudioGenres = sequelize.define('AudioGenres',{},{ timestamps: false });
const AudioMods = sequelize.define('AudioMods',{ timestamps: false });
使用Op.in
查询运算符,用于表联接的数组。
// use the Sequelize.Op query operators,specifically Op.in
const { Op } = require('sequelize');
// these are the values to use for the joins.
const myArrayOfGenreIds = [1,2,...];
const myArrayOfModIds = [1,...];
查询将数组中的ID的两个表连接起来的数组中的值,并返回其中一个不为null的结果。
// now query for Audios joined to Genres and Mods through relationship tables
const audios = await Audio.findAll({
include: [
{
model: Genres,as: 'genres',attributes: [],where: {
id: {
[Op.in]: myArrayOfGenreIds,},{
model: Mods,as: 'mods',where: {
id: {
[Op.in]: myArrayOfModIds,],// only return results from Audios
group: [sequelize.col('audios.id')],having: {
// check to see if the count of IDs we got back matches the count we expect
[Op.and]: [
sequelize.where(
sequelize.fn('COUNT',sequelize.col('genres.id')),myArrayOfGenreIds.length)
),sequelize.where(
sequelize.fn('COUNT',sequelize.col('mods.id')),myArrayOfModIds.length)
),});