Here is my account Model:
module.exports = {
attributes: {
accountPkey: {
type: Sequelize.INTEGER,
primaryKey: true,
field: 'account_pkey'
},
accountName: {
type: Sequelize.STRING,
allowNull: false,
field: 'account_name'
},
imagePkey: {
type: Sequelize.INTEGER,
field: 'image_pkey'
}
},
associations: function() {
Account.hasMany(Privilege, {
as: 'Privileges',
foreignKey: 'account_pkey'
});
Account.hasMany(AccountContact, {
as: 'Contacts',
foreignKey: 'account_pkey'
});
},
options: {
tableName: 'v_account',
timestamps: false,
classMethods: {
whereUserIs(user_pkey, privileges) {
return Account.findAll({
include: [{
model: Privilege,
where: {
'Privilege.privilege_type_name': {
$in: privileges
},
'Privilege.user_pkey': {
$eq: user_pkey
}
}
}]
});
}
},
instanceMethods: {},
hooks: {}
}
};
In my whereUserIs class method I am trying to return all accounts for which there exists a privilege which has the user_pkey and has any of the privileges passed in.
Please assume that the Privilege model has account_type_name and user_pkey properties. Is my syntax correct?
Edit: I am actually using this sails hook to load sequelize: https://www.npmjs.com/package/sails-hook-sequelize
Second Edit:
Here is a more complicated query: I would like to find all users which have a privelege on any of the accounts that were queried above:
User.findAll({
include: [
{
model: Privilege,
include: [
{
model: Account,
include: [{
model: Privelege,
where: {
'Privilege.privilege_type_name': {
$in: privileges
},
'Privilege.user_pkey': {
$eq: user_pkey
}
}
}]
}
]
}
]
})
Does this second one make sense?
In both of these queries, will I get a list of entities (i.e. accounts or users) or will they be nested results (of all the includes)? How can I ensure that my lists of accounts and users are unique/distinct?
Related
I have a problem in findById data with relational sequelize.
Where I have the condition of the One-to-One and Many-to-Many relations
TB_User is related on-to-one with tb_corporate
TB_User is related to many-to-many with TB Corporate and this data relations are saved in TB_corporate_Group
My problem, when I want to get corporate and corporate group. The data I get is data from the user table where the relationship is one-to-one.
this is code in model users
module.exports = (sequelize :any ) => {
class users extends Model{
static associate(models : any) {
// define association here
users.belongsToMany(models.corporate, {
through: 'corporateGroup',
as: 'dataCorporateGroup'
})
users.hasOne(models.corporate, {foreignKey: 'userId', as: 'corporate'})
}
}
users.init({
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
field: 'name',
type: DataTypes.STRING,
allowNull: false,
},
}, {
sequelize,
modelName: 'users',
});
return users;
};
code for model corporate
module.exports = (sequelize :any ) => {
class corporate extends Model{
static associate(models : any) {
// define association here
corporate.belongsTo(models.users, {foreignKey: 'userId', as: 'userCorporate'})
corporate.belongsToMany(models.users, {
through: 'corporateGroup',
as: 'userCorporate'
})
}
}
corporate.init({
userId: {
field: 'user_id',
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
},
corporateName: {
field: 'name',
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
}, {
sequelize,
modelName: 'corporate',
});
return corporate;
};
code for model corporate group
module.exports = (sequelize :any ) => {
class corporateGroup extends Model{
static associate(models : any) {
// define association here
}
}
corporateGroup.init({
corporateId: {
field: 'corporate_id',
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'corporate',
key: 'id'
}
},
userId: {
field: 'user_id',
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}
}, {
sequelize,
tableName: 'corporate_group',
modelName: 'corporateGroup',
});
return corporateGroup;
};
and this code for find by id
await corporate.findById(id, {
include: [{
model: db.users,
as: 'userCorporate',
}]
})
You need to indicate the unique aliases for associations
corporate.belongsTo(models.users, {foreignKey: 'userId', as: 'userCorporate'})
corporate.belongsToMany(models.users, {
through: 'corporateGroup',
as: 'corporateGroupUsers'
})
and then you can indicate included models with these aliases to get both of them along with corporate record:
await corporate.findById(id, {
include: [{
model: db.users,
as: 'userCorporate',
}, {
model: db.users,
as: 'corporateGroupUsers',
}]
})
I'm working on an API in Node.js with the Sequelize ORM.
I make an API route to retrieve a random question, it works one time out of three but often returns an empty array. I can't find a solution in the documentation to prevent this...
app.get('/:certifName/:levelName/random', async function (req, res) {
return await Certification.findOne(
{
attributes: ['id', 'label'],
include: [{
model: CertificationLevel,
as: "tcl",
required: true,
attributes: ['id', 'label', 'question_number', 'exam_duration'],
include: [{
attributes: ['id', 'label'],
model: CertificationChapter,
as: "tcc",
required: true,
limit: 1,
order: [ [ Sequelize.fn('RANDOM') ] ],
include: [{
model: Question,
as: "tq",
required: true,
include: [{
model: QuestionChoice,
as: "tqc",
required: false,
attributes: ['id', 'label_fr', 'is_answer'],
}],
}],
}],
where: { label: req.params.levelName }
}],
where: { label: req.params.certifName }
})
.then(data => {
if (data) {
res.send(data);
}
else
res.sendStatus(204);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Error retrieving certification details"
});
});
});
The last model :
module.exports =
class CertificationLevel extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
label: Sequelize.STRING,
slug: Sequelize.STRING,
description: Sequelize.TEXT,
question_number: Sequelize.INTEGER,
exam_duration: Sequelize.INTEGER,
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
},
updated_at: Sequelize.DATE,
deleted_at: Sequelize.DATE
},
{
tableName: 't_certifications_levels',
sequelize,
underscored: true,
timestamps: false
},
);
}
static associate(models) {
this.belongsTo(models.Certification, {
onDelete: "CASCADE",
foreignKey: {
allowNull: false,
name: "certification_id"
}
}),
this.hasMany(models.CertificationChapter, { as:'tcc', foreignKey: 'level_id' })
this.hasMany(models.Subscription, { as:'ts',foreignKey: 'level_id' })
}
}
And this is a SQL query generate :
SELECT "Certification".*,
"tcl"."id" AS "tcl.id",
"tcl"."label" AS "tcl.label",
"tcl"."question_number" AS "tcl.question_number",
"tcl"."exam_duration" AS "tcl.exam_duration"
FROM
(SELECT "Certification"."id",
"Certification"."label"
FROM "t_certifications" AS "Certification"
WHERE "Certification"."label" = 'ISTQB'
AND
(SELECT "tcl"."certification_id"
FROM "t_certifications_levels" AS "tcl"
WHERE ("tcl"."label" = 'Fondation'
AND "tcl"."certification_id" = "Certification"."id")
LIMIT 1) IS NOT NULL
LIMIT 1) AS "Certification"
INNER JOIN "t_certifications_levels" AS "tcl" ON "Certification"."id" = "tcl"."certification_id"
AND "tcl"."label" = 'Fondation';
I don't know why I have two executing to my route?
I am a real beginner in back development...
Thank for you help
I'm trying to implementing this mysql command on sequelize, but as far as i'm newbie to use this library i can't implementing that
i want to make this sql command:
SELECT * FROM users
join users_contacts_lists on users_contacts_lists.mobile_number = users.mobile_number
WHERE users_contacts_lists.user_id = 1
My models to create database schema:
'use strict';
var config = require('../config');
var User = config.sequelize.define('users', {
id: {
type: config.Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
password: {
type: config.Sequelize.STRING
},
username: {
type: config.Sequelize.STRING
},
mobileNumber: {
type: config.Sequelize.STRING,
field: 'mobile_number'
},
status: {
type: config.Sequelize.STRING
},
}, {freezeTableName: true});
var UsersContactsLists = config.sequelize.define('users_contacts_lists', {
id: {
type: config.Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
userId: {
type: config.Sequelize.INTEGER,
field: 'user_id'
},
mobileNumber: {
type: config.Sequelize.STRING,
field: 'mobile_number', defaultValue: 0
}
}, {freezeTableName: true});
UsersContactsLists.belongsTo(ChannelsTypes, {foreignKey: 'user_id'});
User.hasMany(Channels, {foreignKey: 'id'});
User.sync();
UsersContactsLists.sync();
module.exports =
{
users: User,
usersContactsLists: UsersContactsLists
};
how can i resolve this problem? Thanks in advance
You can define the target key and the foreign key both in a relation like this:
User.belongsTo(UsersContactsLists, {targetKey:'mobileNumber',foreignKey: 'mobileNumber'});
And then you can use this:
User.findAll({
include: [{
model: UsersContactsLists,
where: {
userId: 1
}
}]
})
Fiddled around a bit, does this statement do what you want?
User.findAll({
include: [{
model: UsersContactsLists,
where: {
userId: 1
}
}]
Tables have many to many relationship, junction by an order table in between.
Outlet --> Order <-- Product
I want to get the list of Outlet for today Order.
So here is a function to get all outlets:
db.Outlet.findAll({include: [
{model:db.Product, attributes: ['id', 'name', 'nameKh']}
]}).then(function(outlets){
return res.jsonp(outlets);
})
I got this result:
I can only select with where Product Id by using this:
db.Outlet.findAll({include: [
{model:db.Product, attributes: ['id', 'name', 'nameKh'], where: {id: 2}
]}).then(function(outlets){
return res.jsonp(outlets);
})
How can I query by specific order amount, or today order date?
Here are my models:
Outlet:
var Outlet = sequelize.define('Outlet', {
outletCode: DataTypes.STRING,
outletName: DataTypes.STRING,
outletNameKh: DataTypes.STRING,
outletSubtype: DataTypes.STRING,
perfectStoreType: DataTypes.STRING,
address: DataTypes.STRING
},
{
associate: function(models){
Outlet.belongsToMany(models.Product, {through: models.Order});
Outlet.belongsTo(models.Distributor);
// Outlet.hasMany(models.Order);
}
}
);
Product:
var Product = sequelize.define('Product', {
inventoryCode: DataTypes.STRING,
name: DataTypes.STRING,
nameKh: DataTypes.STRING,
monthlyCaseTarget: DataTypes.INTEGER,
pieces: DataTypes.INTEGER,
star: DataTypes.BOOLEAN,
price: DataTypes.FLOAT,
active: DataTypes.BOOLEAN
},
{
associate: function(models){
Product.belongsToMany(models.Outlet, {through: models.Order});
Product.belongsTo(models.Category);
// Product.hasMany(models.Order);
}
}
);
Order:
var Order = sequelize.define('Order', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
amount: DataTypes.INTEGER
},
{
associate: function(models){
Order.belongsTo(models.Outlet);
Order.belongsTo(models.Product);
Order.belongsTo(models.User);
}
}
);
Try it:
db.Outlet.findAll({
include: [{
model:db.Product,
attributes: ['id', 'name', 'nameKh'],
through: { where: { amount: 10 } }
}]
})
Similar case
Super many to many relatioship
User.belongsToMany(Profile, { through: Grant });
Profile.belongsToMany(User, { through: Grant });
User.hasMany(Grant);
Grant.belongsTo(User);
Profile.hasMany(Grant);
Grant.belongsTo(Profile);
This way, we can do all kinds of eager loading:
// All these work:
User.findAll({ include: Profile });
Profile.findAll({ include: User });
User.findAll({ include: Grant });
Profile.findAll({ include: Grant });
Grant.findAll({ include: User });
Grant.findAll({ include: Profile });
We can even perform all kinds of deeply nested includes:
User.findAll({
include: [
{
model: Grant,
include: [User, Profile]
},
{
model: Profile,
include: {
model: User,
include: {
model: Grant,
include: [User, Profile]
}
}
}
]
});
From sequelize doc
I have two sequelize models with one-to-many relationship. Let's call them Owner and Property.
Assume they are defined using the sails-hook-sequelize as such (simplified).
//Owner.js
module.exports = {
options: {
tableName: 'owner'
},
attributes: {
id: {
type: Sequelize.BIGINT,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING(255)
},
associations: function () {
Owner.hasMany(Property, {
foreignKey: {
name: 'owner_id'
}
});
}
}
//Property.js
module.exports = {
options: {
tableName: 'property'
},
attributes: {
id: {
type: Sequelize.BIGINT,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING(255)
}
}
Now assume I want to insert an Owner record in my database and insert a few property records to associate with the owner. How do I do this?
I'm looking for something like
Owner.create({name:'nice owner',
property: [{name:'nice property'},
{name:'ugly property'}]});
Surprisingly I can't find this in the Sequelize documentation.
You can't associate property existing records when you create the owner, you have to do that right after, with promise chain.
Owner.create({name:'nice owner'}).then(function(owner){
owner.setProperties([{name:'nice property'}, {name:'ugly property'}]).then(/*...*/);
});
To avoid any problems with those associations (owner created but some associations failed), it's better to use transactions.
sequelize.transaction(function(t) {
return Owner.create({name:'nice owner'}, {transaction: t}).then(function(owner){
return owner.setProperties([{name:'nice property'}, {name:'ugly property'}], {transaction : t});
});
});
However, if you want to create new Owner associated to new Properties you can do something like
Owner.create({
name: 'nice owner',
property: [
{ name: 'nice property'},
{ name: 'ugly property'}
]
},{
include: [ Property]
});
See http://docs.sequelizejs.com/en/latest/docs/associations/#creating-with-associations