I'm trying to make a filter songs, i have an array of genres ids that i retrieve from the client, i do this for get all the audios from one id:
Audio.findAll({
include: [{
model: db.Genres,
as: "genres",
where: {
id: {
[Op.and]: [1]
}
},
}]
})
But i need to get all audios that contains all the ids from array of genres/moods, also want filter audios by genres ids and moods ids, but i don't know how to make it, any idea? (One song can have many genres/moods)
Song Model
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.Moods, {through: 'AudioMoods', foreignKey: 'id_audio', as: 'moods'})
}
AudioGenreModel
const AudioGenres = sequelize.define('AudioGenres', {
id_audio: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Audio',
key: 'id'
}
},
id_genre: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Genres',
key: 'id'
}
})
AudioGenres.associate = function(models) {
AudioGenres.belongsTo(models.Audio, {foreignKey: 'id_audio'})
AudioGenres.belongsTo(models.Genres, {foreignKey: 'id_genre'})
};
AudioMoodModel
const AudioMoods = sequelize.define('AudioMoods', {
id_audio: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Audio',
key: 'id'
}
},
id_mood: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Mods',
key: 'id'
}
})
AudioMoods.associate = function(models) {
AudioMoods.belongsTo(models.Audio, {foreignKey: 'id_audio'})
AudioMoods.belongsTo(models.Mods, {foreignKey: 'id_mood'})
};
Moods and Genres Model
const Moods = sequelize.define('Moods', {
name: {
type: DataTypes.STRING(255),
allowNull: false
},
})
Moods.associate = function(models) {
Moods.belongsToMany(models.Audio, {through: 'AudioMoods', foreignKey: 'id_mood', as: 'audios'})
}
const Genres = sequelize.define('Genres', {
name: {
type: DataTypes.STRING(255),
allowNull: false
},
})
Genres.associate = function(models) {
Genres.belongsToMany(models.Audio, {through: 'AudioGenres', foreignKey: 'id_genre', as: 'audios'})
}
I suppose you should add all conditions in AND operator in both include options like this:
Audio.findAll({
include: [{
model: db.Genres,
as: "genres",
where: {
[Op.and]: [{ id: 1}, { id: 3},{ id: 2}]
},
}, {
model: db.Moods,
as: "moods",
where: {
[Op.and]: [{ id: 4}, { id: 5},{ id: 6}]
},
}]
})
Related
I dont know why I am getting this error error: SequelizeDatabaseError: Unknown column 'student-> section ->grademapping.studentId' in 'field list' I just follow this documentation on how to use belongsToMany did i miss something on the documentation? https://sebhastian.com/sequelize-belongstomany/
let student = await Database.getConnection().models.Student;
let grademapping = await Database.getConnection().models.Grademapping;
let section = await Database.getConnection().models.Section;
let taxtypemapping = await student.findAll({
attributes:['_id','FirstName','LastName', 'section.Description'],
include:[
{ model: section, attribute:[] }
],
raw: true
})
the models
class taxtypedetails extends Sequelize.Model {}
Section.init(
{
_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Description: {
type: Sequelize.STRING,
},
},
{ sequelize, tableName: 'section', timestamps: false },
)
class Student extends Sequelize.Model {}
Student.init(
{
_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
FirstName: {
type: Sequelize.STRING,
},
LastName: {
type: Sequelize.STRING,
},
},
{ sequelize, tableName: 'student', timestamps: false },
)
class Grademapping extends Sequelize.Model {}
Grademapping.init(
{
_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
sectionID: {
type: Sequelize.INTEGER,
references: {
model: 'section',
key: '_id',
},
},
studentID: {
type: Sequelize.INTEGER,
references: {
model: 'student',
key: '_id',
},
}
},
{ sequelize, tableName: 'grademapping', timestamps: false },
)
student.belongsToMany(section,{through: grademapping})
section.belongsToMany(student,{through: grademapping})
I have a model defined as follows:
sequelize.define('game', {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
leaderId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
playerId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
status: {
type: type.STRING,
defaultValue: 'running',
},
notes: {
type: type.TEXT,
},
});
I'm trying to use Sequelize to load all game object and include the User with the id equal to the playerId field.
The problem is I have two attributes (leaderId, playerId) which reference the User model so using include as follows does not work:
Game.findAll({
where: conditions,
include: [{ model: User }],
})
Is there a way to specify which attribute the include command should use?
const game = sequelize.define('game', {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
leaderId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
playerId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
as:'player'
},
status: {
type: type.STRING,
defaultValue: 'running',
},
notes: {
type: type.TEXT,
},
});
game.associate = function (models) {
game.belongsTo(models.user, {
foreignKey: "playerId",
as: "player",
});
game.belongsTo(models.user, {
foreignKey: "leaderId",
as: "leader",
});
};
Game.findAll({
where: conditions,
include: ['player'],
})
Or
Game.findAll({
where: conditions,
include: [{model: User, as: 'player' }],
})
Or
Game.findAll({
where: conditions,
include: [{model: User, as: 'player', foreignKey: 'playerId' }],
})
https://github.com/nkhs/node-sequelize
I defined Cars, Brands, and Images. Cars return all images but it returns Brand as null. (I don't show the definition of Images because it is working just fine, unlike Brand)
Each car has only one brand and multiple images so I defined as follows:
Cars.associate = models => {
Cars.hasOne(models.brands, {
foreignKey: {
name: 'id',
allowNull: false
},
sourceKey: 'brand_id',
required : true
}),
Cars.hasMany(models.car_images, {
foreignKey: {
name: 'car_id',
allowNull: false
},
onDelete: "cascade"
})
};
Then I defined Brands and I associated to Cars:
CarBrands.associate = models => {
CarBrands.belongsTo(models.cars, {
sourceKey: 'id',
foreignKey: {
name: 'id',
}
});
The SQL is built fine, all the information is returned yet when I query the GraphQL brand returns always null:
SELECT `cars`.`id`, `cars`.`user_id`, `cars`.`title`, `cars`.`created_at`, `cars`.`updated_at`, `brand`.`id` AS `brand.id`, `brand`.`name` AS `brand.name`, `brand`.`status` AS `brand.status`, `car_images`.`id` AS `car_images.id`, `car_images`.`car_id` AS `car_images.car_id`, `car_images`.`image` AS `car_images.image`, `car_images`.`created_at` AS `car_images.created_at`, `car_images`.`updated_at` AS `car_images.updated_at` FROM `cars` AS `cars` LEFT OUTER JOIN `brands` AS `brand` ON `cars`.`brand_id` = `brand`.`id` LEFT OUTER JOIN `car_images` AS `car_images` ON `cars`.`id` = `car_images`.`car_id`;
When I query:
brand_name {
name
}
It returns:
"brand_name": null
The definitions are as follows:
Cars.js
export const typeDef = `
type Cars {
user_id: Int!,
title: String!,
brand_id: Int!,
brand_name: [CarBrands],
car_images: [CarImages]
}
`;
export const resolvers = {
Query: {
async getAllCars (root, args, { models }) {
return models.cars.findAll({
include: [{ all: true, nested: true }]
})
},
}
};
CarBrands.js
export const typeDef = `
type CarBrands {
id: Int!,
name: String,
status: Int
}
`;
cars.js
module.exports = function(sequelize, DataTypes) {
const Cars = sequelize.define('cars', {
'id': {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
comment: "null",
autoIncrement: true
},
'user_id': {
type: DataTypes.INTEGER(11),
allowNull: true,
comment: "null"
}
}, {
updatedAt: 'updated_at',
createdAt: 'created_at',
tableName: 'cars',
underscored: true
});
Cars.associate = models => {
Cars.hasOne(models.brands, {
foreignKey: {
name: 'id',
allowNull: false
},
sourceKey: 'brand_id',
required : true
}),
Cars.hasMany(models.car_images, {
foreignKey: {
name: 'car_id',
allowNull: false
},
onDelete: "cascade"
})
};
return Cars;
};
brands.js
module.exports = function(sequelize, DataTypes) {
const CarBrands = sequelize.define('brands', {
'id': {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
comment: "null",
autoIncrement: true
},
'name': {
type: DataTypes.STRING(255),
allowNull: true,
comment: "null"
},
'status': {
type: DataTypes.INTEGER(3),
allowNull: false,
defaultValue: '1',
comment: "null"
}
}, {
timestamps: false,
tableName: 'brands'
});
CarBrands.associate = models => {
CarBrands.belongsTo(models.cars, {
sourceKey: 'id',
foreignKey: {
name: 'id',
}
});
};
return CarBrands;
};
Any idea where is the problem?
Thanks!
I am working on a NodeJs application using sequelize as an ORM with exciting database , so I had to use sequelize model generator in order to generate the models for my application.
Here's an example of the generation output:
Category.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('category', {
id: {
type: DataTypes.STRING(128),
allowNull: false,
primaryKey: true,
field: 'id'
},
name: {
type: DataTypes.TEXT,
allowNull: true,
field: 'name'
}
}, {
tableName: 'category'
});
};
Product.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('product', {
id: {
type: DataTypes.STRING(128),
allowNull: false,
primaryKey: true,
field: 'id'
},
category: {
type: DataTypes.STRING(128),
allowNull: false,
references: {
model: 'category',
key: 'id'
},
field: 'category'
},
name: {
type: DataTypes.TEXT,
allowNull: true,
field: 'name'
}
}, {
tableName: 'product'
});
};
and then inside my controller I have this query :
models.product.findOne({
where: {
id: req.body.id
}
}).then(function (obj) {
//return the product data
console.log(product.category) //works
console.log(product.category.name) //return undefined
});
The question is how can I access to the parent table attribute via the same query findOne ? Is there something like or equivalent to product.category.id ?
if you have associated both the models... then try this
module.exports = function(sequelize, DataTypes) {
return sequelize.define('product', {
id: {
type: DataTypes.STRING(128),
allowNull: false,
primaryKey: true,
field: 'id'
},
category_id: {
type: DataTypes.STRING(128),
allowNull: false,
references: {
model: 'category',
key: 'id'
},
field: 'category'
},
name: {
type: DataTypes.TEXT,
allowNull: true,
field: 'name'
}
}, {
tableName: 'product'
});
}
models.product.findOne({
where: {
id: req.body.id
},
include: [{
model: category,
required: false
}]
}).then(function (obj) {
//return the product data
console.log(product.category) //works
console.log(product.category.name) //return undefined
});
Associate like this
product.hasMany(db.category, {
foreignKey: 'category_id',
onDelete: 'cascade'
});
category.belongsTo(db.product, {
foreignKey: 'category_id',
targetKey: 'id',
constraints: true
});
Considering these 3 models generated by sequelize-auto:
sequelize.define('users', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
first: {
type: DataTypes.STRING,
allowNull: true
},
last: {
type: DataTypes.STRING,
allowNull: true
}
}, {
tableName: 'users',
underscored: true,
timestamps: false
});
sequelize.define('groups', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
parent_id: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'groups',
key: 'id'
}
}
}, {
tableName: 'groups',
underscored: true,
timestamps: false
});
sequelize.define('user_groups', {
group_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
references: {
model: 'groups',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}
}, {
tableName: 'user_groups',
underscored: true,
timestamps: false
});
I was expecting hasOne statements to be generated but I had to specify them like so:
user_groups.hasOne(orm.models.users, { foreignKey: "id" });
user_groups.hasOne(orm.models.groups, { foreignKey: "id" });
Also consider the following data in tables:
users (id, first, last):
1, John, Doe
group (id, parent_id):
1, NULL
2, NULL
3, NULL
4, NULL
user_groups (group_id, user_id):
1, 1
4, 1
Doing this query:
sequelize.findAll("user_groups", {
attributes: ["*"],
raw: true,
include: [{
model: models.users,
}]
});
I get the following results:
[ { group_id: 4,
user_id: 1,
'user.id': null,
'user.first': null,
'user.last': null },
{ group_id: 1,
user_id: 1,
'user.id': 1,
'user.first': 'John',
'user.last': 'Doe' } ]
This clearly shows that sequelize is using group_id for the user_id relation.
How can I specify a relation that links the user_groups relations to their respective tables in order to be able to associate a user to many groups?
I am also very curious as how the "references" key in the models definition is supposed to work as the documentation is inexistant on that.
I was able to get the referenced data using these associations:
groups.hasMany(orm.models.user_groups);
user_groups.belongsTo(orm.models.groups, {foreignKey: "group_id", as: "group"});
users.hasMany(orm.models.user_groups);
user_groups.belongsTo(orm.models.users, {foreignKey: "user_id", as: "user"});
And the following query:
sequelize.findAll("user_groups", {
attributes: ["*"],
raw: true,
include: [
{ model: users, foreignKey: "user_id", as: "user", attributes: ["first", "last"] }
]
});
With the expected results:
[ { group_id: 4,
user_id: 1,
'user.first': 'John',
'user.last': 'Doe' },
{ group_id: 1,
user_id: 1,
'user.first': 'John',
'user.last': 'Doe' } ]