How to query associated models in Node/Postgres - node.js

I'm building an app in express and I'm using postgres and sequelize for ORM. I have two models, User and Post.
In my user.js and post.js files I have:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: ""
},
module.exports = function(sequelize, DataTypes) {
return sequelize.define('posts', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER,
allowNull: true
},
title: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: ""
},
I imported those two models and I made the following associations:
User.hasMany(Post, { foreignKey: 'user_id' });
Post.belongsTo(User, { foreignKey: 'user_id' });
I am trying to render all the posts done by a user, but I'm probably missing something.
In my routes I can get the correct user but I don't know how to proceed.
router.route('/:id').get(async (req, res) => {
const user = await User.findById(req.params.id);
console.log(user);
res.send(user);
})
Thanks!

findById does not support the associated model ,
User.findById(req.params.id);
You can change findById to findOne and include model like this ,
User.findOne({
where : { id : req.params.id },
include : {
model : Post
}
});

Related

How to make sequelize model seperate file but same sequelize connection

everyone. I'm very new for sequelize ORM with nodejs.
I've just created couple files for models seperately and I also seperate sequelize.js to connect to database.
The problem is when I make association between model(file)(Self Associate work well) and I've got an error
**** "hasMany called with something that's not a subclass of Sequelize.Model"
I tried to solved this but doesn't work until I put every model in the same file. So, I realized that every model must use common sequelize connection.
Is there anyways to solve this problem without sequelize-cli (I don't want to use sequelize-cli)
My code belows
Many thanks,
sequelize.js
const config = require("config");
const { Sequelize } = require("sequelize");
const sequelize = new Sequelize(
config.get("database"),
config.get("user"),
config.get("cipher"),
{
dialect: "mariadb",
timezone: "Asia/Bangkok",
}
);
module.exports = sequelize;
user.js
const { DataTypes, Model } = require("sequelize");
const sequelize = require("./sequelize");
const Position = require("./position");
class User extends Model {}
User.init(
{
uuid: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
firstname: {
type: DataTypes.STRING,
allowNull: false,
},
lastname: {
type: DataTypes.STRING,
allowNull: false,
},
phone: {
type: DataTypes.STRING,
allowNull: true,
},
email: {
type: DataTypes.STRING,
allowNull: true,
validate: {
isEmail: true,
},
},
imgurl: {
type: DataTypes.STRING,
allowNull: true,
},
login: {
type: DataTypes.STRING,
allowNull: false,
},
passphase: {
type: DataTypes.STRING,
allowNull: false,
},
status: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1,
},
},
{
sequelize,
modelName: "User",
tableName: "users",
timestamps: true,
}
);
User.belongsToMany(User, {
as: "CreatedUser",
foreignKey: "user_id",
through: "UserCreator",
});
User.belongsToMany(User, {
as: "Creator",
foreignKey: "creator_id",
through: "UserCreator",
});
User.belongsToMany(User, {
as: "ModifiedUser",
foreignKey: "user_id",
through: "UserModifier",
});
User.belongsToMany(User, {
as: "Modifier",
foreignKey: "modifier_id",
through: "UserModifier",
});
User.belongsTo(Position);
module.exports = User;
position.js
const { DataTypes, Model } = require("sequelize");
const sequelize = require("./sequelize");
const User = require("./user");
class Position extends Model {}
Position.init(
{
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
status: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1,
},
},
{
sequelize,
modelName: "Position",
tableName: "postions",
timestamps: true,
}
);
Position.hasMany(User, {
foreignKey: {
type: DataTypes.UUIDV4,
allowNull: false,
},
});
module.exports = Position;
Sequelize has a .define() method to create all your schemas in JSON. If you want to keep your connection to the database separate from your models, I suggest doing something like this
./models/schemas/User.js
const userSchema = {
attribute1: {
type: ...,
option1: ...,
option2: ...,
.
.
},
.
.
}
export default userSchema
Do the same with Position.js
Then:
./models/models.js
import {sequelize} from 'path/to/sequelize.js'
import positionSchema from './schemas/Position.js'
import userSchema from './schemas/User.js'
const User = sequelize.define("user", userSchema, { freezeTableName: true });
const Position = sequelize.define("position", positionSchema, { freezeTableName: true });
// add associations
export {
User,
Position,
.
.
}

How to solve problem with filter in Sequelize with belongsToMany association

I using Sequelize with Node and Express.
I have created two models - User and Task with Many-to-Many associacion
const User = sequelize.define('user', {
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false },
username: { type: Sequelize.STRING, allowNull: false, unique: true },
password: { type: Sequelize.STRING, allowNull: false }
})
and
const Task = sequelize.define('task', {
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false },
title: { type: Sequelize.STRING, allowNull: false }
})
Many-to-Many associacion
User.belongsToMany(Task, {
through: "user_tasks",
foreignKey: "userId",
otherKey: "taskId"
})
Task.belongsToMany(User, {
through: "user_tasks",
foreignKey: "taskId",
otherKey: "userId"
})
I'm trying to find tasks for user with id userId with following code:
const tasks = await Task.getTasks(
{ through: { where: { userId: request.userId } } }
)
But i have an Error:
TypeError: Task.getTasks is not a function"
If you want one users and their tasks do something like this?
const user = await User.findByPk(request.userId)
const userTasks = await user.getTasks()

User is not associated to Temperature. Sequelize Eager loading error

In my application every user can record many temperatures, but one temperature record should have only one user. I am trying to execute the following code and facing an 'User is not associated with Temperature' Error. Please review my code below and let me know where i have gone wrong.
This is my User model
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = require('../connection');
var Temperature = require('./temperature');
var User = sequelize.define('User', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
},
status: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'Active'
},
role: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'Admin'
}
});
User.associate = (models) => {
User.hasMany(models.Temperature, { as: 'temperatures' })
}
module.exports = User;
This is my Temperature model
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = require('../connection');
const User = require('./users');
var Temperature = sequelize.define('Temperature', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
userId: {
type: DataTypes.INTEGER,
allowNull: false,
},
temperature: {
type: DataTypes.FLOAT,
allowNull: false
},
recordDateTime: {
type: DataTypes.DATE,
allowNull: false
}
});
Temperature.associate = (models) => {
Temperature.belongsTo(models.User, { foreignKey: 'userId', as: 'user' })
}
module.exports = Temperature;
I am getting error in running the following code
Temperature.findAll({ include: User, raw:true})
.then((res)=>{
console.log(res);
})
Can you anyone please help in figuring out this issue.
The associate functions in both the models are not executing.
you don't need to add userId column into Temperature model schema, just define associations as you have already did and even if you want to add userId column in model schema the do it like below but must add it in migration file of your Temperature model schema like below
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'Users', // <----- name of the table
key: 'id' // <----- primary key
}
}

(Sequelize+Postgres+NodeJS) Inster FK (userID) from another table

I'm using Sequelize connected to PostgreSQL and as I want to use sync function I would like to prepare valid models to create tables on every environment.
EDIT:
Wallet:
'use strict';
module.exports = function(db, DataTypes) {
var Wallet = db.define('Wallet', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
money: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE
}, {
tableName: 'wallet',
classMethods:{
associate : function( models ) {
Wallet.belongsTo( models.User,{ foreignKey : 'id_user'});
}
}
});
return Wallet;
};
User:
'use strict';
var bcrypt = require('bcrypt-nodejs');
var crypto = require('crypto');
var moment = require('moment');
var models = require('./');
var afterCreateHook = function(user, options, fn) {
models.Wallet.build({id_user: user.id}).save();
fn(null, user);
};
module.exports = function(db, DataTypes) {
var User = db.define('User', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
password: DataTypes.STRING,
email: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
isEmail: true
},
login: {
type: DataTypes.STRING,
unique: true,
allowNull: false
}
}, {
tableName: 'pl_users',
instanceMethods: instanceMethods,
classMethods: {
associate : function( models ) {
User.hasOne( models.Wallet);
}
},
hooks: {
afterCreate: afterCreateHook
}
});
return User;
};
Why
models.Wallet.build({id_user: user.id}).save();
is not working? Account is creating and then I want to create wallet with specific user_id. I don't have even an error...
Help please!
You should check relations from sequelize docs
In your case youu need to define:
Wallet.belongsTo(User,{foreignKey: 'id_user'});
This will add id_user to Wallet model , so you dont need to specify id_user attribute in your WalletModel.
If you are using sequelize import function , you should add the relation in "associate" class method like this:
module.exports = function(db, DataTypes) {
var Wallet = db.define('Wallet', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
pin: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
},
money: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 0
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE
}, {
tableName: 'Wallet',
classMethods:{
associate : function( models ) {
Wallet.belongsTo( models.User,{ foreignKey : 'id_user'});
}
}
});

Sequelize eager loading association with through table

I've been through several questions on the site but I still can't see what I'm doing wrong here, so any help would be greatly appreciated.
I'm getting the error:
Organization (organizations) is not associated to User!
Org Model:
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Organization', {
organizationID: {
primaryKey: true,
type: DataTypes.INTEGER(11),
allowNull: false,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.STRING,
allowNull: true,
}
},
{
tableName: "spa_vOrganization",
freezeTableName: true,
classMethods: {
associate: function (models) {
Organization.hasMany(models.User, {
as: 'users',
through: models.User_Tenant_Organization,
foreignKey: 'organizationID'
});
}
},
});
};
User Model:
module.exports = function (sequelize, DataTypes) {
return sequelize.define('User', {
userID: {
primaryKey: true,
type: DataTypes.INTEGER(11),
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
}
},
{
tableName: "spa_User",
freezeTableName: true,
classMethods: {
associate: function(models) {
User.hasMany(models.Organization, { as: "organizations", through: models.User_Tenant_Organization, foreignKey: 'userID'});
}
}
}
);
};
Matrix table model:
module.exports = function (sequelize, DataTypes) {
return sequelize.define('User_Tenant_Organization', {
userTenantOrganizationID: {
primaryKey: true,
type: DataTypes.INTEGER(11),
allowNull: false,
},
userID: {
type: DataTypes.INTEGER(11),
allowNull: false,
},
organizationID: {
type: DataTypes.INTEGER(11),
allowNull: false,
},
tenantID: {
type: DataTypes.INTEGER(11),
allowNull: false,
},
},
{
tableName: "spa_User_Tenant_Organization",
freezeTableName: true,
});
};
What I'm trying to do is just pull back a user with their organizations eagerly loaded. Here's what I'm using:
models.User.findOne({where: {
email: body.email
}, include: [ {model:models.Organization, as: 'organizations'}]}).complete( function (err, user) {
// do something with the user
}
I've tried with and without foreignKey definitions on both User and Organization, nothing makes any difference. I'm obviously misunderstanding something about the associations. Can anyone tell me where I'm going wrong please?
I found the problem. The associations in the above code are actually correct - what was failing was my models/index.js, which had been automatically generated by the yeoman generator-angular-express-sequelize
index.js was looping through the model files, importing them into the sequelize object and storing a copy in an array db[], then trying to run the classMethod associate(), but it was calling models.options.associate() instead of models.associate():
Object.keys(db).forEach(function (modelName) {
if (db[modelName].options.hasOwnProperty('associate')) {
db[modelName].options.associate(db);
}
});
I've fixed that by removing the ".options" and everything works fine.
Pull request to fix the problem is here for reference: https://github.com/rayokota/generator-angular-express-sequelize/pull/7

Resources