User is not associated to Temperature. Sequelize Eager loading error - node.js

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
}
}

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()

How to access the data from mapping table in graphql using sequelize

i am new to sequelize, i have a user table , address table and address type table as given below.
A user can have 2 a different address , permanent and current address, and the type of address (permanent or current ) is specified in the table address type.
I have tried to access the data from mapping table (address_type) in the resolver based on schema and set hasMany relation from user -> address table , but graphql shows association not found error.
How can we get the relation properly in order to get the mapping address type name.
type User{
id:Int
name:String
}
type Address {
id: ID!
user_id:Int
city: String
addr_type:AddressType
}
type AddressType{
id : Int
name:String (permanent|current)
}
table definition
module.exports = function(sequelize, DataTypes) {
return sequelize.define('user', {
id: {
type: DataTypes.INTEGER, allowNull: false, primaryKey: true, autoIncrement: true
},
name: {
type: DataTypes.INTEGER, allowNull: false,
},
}, {
tableName: 'user',
timestamps: false
});
};
module.exports = function(sequelize, DataTypes) {
return sequelize.define('address', {
id: {
type: DataTypes.INTEGER, allowNull: false, primaryKey: true, autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER, allowNull: false, field:"addr_type"
},
addr_type: {
type: DataTypes.INTEGER, allowNull: false, field:"addr_type"
},
city: {
type: DataTypes.STRING, allowNull: false,
},
}, {
tableName: 'address',
timestamps: false
});
};
module.exports = function(sequelize, DataTypes) {
return sequelize.define('address_types', {
id: {
type: DataTypes.INTEGER, allowNull: false, primaryKey: true, autoIncrement: true
},
name: {
type: DataTypes.STRING, allowNull: false,
},
}, {
tableName: 'address_type',
timestamps: false
});
};
relationship
db.user.hasMany(db.address,{foreignKey: 'user_id'});
db.address.belongsTo(db.user,{foreignKey: 'user_id'});
db.address.belongsTo(db.address_types,{foreignKey: 'addr_type'});
resolver code
userts: async (obj, args, context, info ) => User.findAll( {
where: { user_status: 1 },
,
raw: true,
nest: true,
} ).then(userts => {
const response = userts.map(usert => {
return{
// i have 15 fields for a user, if i can access the schema of the corresponsing resolver i can dynamically build the response out put
id: usert.id,
firstName: usert.firstName,
lastName: usert.lastName,
middleName: usert.middleName,
}
})
return response;
}),
You should turn off the option raw in order to get associated objects and use the include option to indicate what associated models you wish to load.
User.findAll( {
where: { user_status: 1 },
include: [{
model: Address,
include: AddressType
}],
raw: false,
nest: true,
}

How can I create an accociation to a specific key using Sequelize?

I have my models all set up, and I have a foreign key from one table to another using the tables ID. I also want to have the url property as a foreign key, but whenever I include "type: DataTypes.STRING', I get the following error
Unhandled rejection SequelizeDatabaseError: (conn=195, no: 1215, SQLState: HY000) Cannot add foreign key constraint
When I don't include the datatype, it adds the FK, but as an integer. How can I create a FK that specifically references the URL property?
Thanks
categories.belongsTo(categoriesTop, {
foreignKey: {
name: 'topCategoriesUrl',
allowNull: false,
type: DataTypes.STRING,
referencesKey: "url"
}
});
Categories_top schema
const { Sequelize, DataTypes } = require('sequelize');
const db = require('../dbconfig');
const categories_top = db.define('categories_top', {
url: {
type: DataTypes.STRING,
allowNull: false
},
title: {
type: DataTypes.STRING,
allowNull: false
},
subtitle: {
type: DataTypes.STRING,
allowNull: false
},
image: {
type: DataTypes.STRING
}
}, {
freezeTableName: true,
timestamps: false
});
module.exports = categories_top;
categories schema
const { Sequelize, DataTypes } = require('sequelize');
const db = require('../dbconfig');
const topCategories = require('./category_top');
const categories = db.define('categories', {
title: {
type: DataTypes.STRING,
allowNull: false
},
subtitle: {
type: DataTypes.STRING,
allowNull: true
},
url: {
type: DataTypes.STRING,
allowNull: false
},
image: {
type: DataTypes.STRING
}
}, {
freezeTableName: true,
timestamps: false
});
module.exports = categories;
You have to define url in category_top as a primary key or a unique constraint, like this:
const categories_top = db.define('categories_top', {
url: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true, // Either define it as a primary key
unique: true // OR as a unique constraint
},
title: {
type: DataTypes.STRING,
allowNull: false
},
subtitle: {
type: DataTypes.STRING,
allowNull: false
},
image: {
type: DataTypes.STRING
}
}, {
freezeTableName: true,
timestamps: false
});
Read more about foreign keys here.

(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'});
}
}
});

Resources