Sequelize creating 2 entries instead of 1 - javascript

I have 2 models, patient & personalInformation.
There is an association such that personalInformation.belongsTo(patient). In my case, the patient primary key or uuid exists as a column in the personalInformation table.
When my API receives a single POST request, I intend to make my controller create a patient entry and personalInformation entry together.
This is my controller code:
// patient.controller.js
const db = require('../../db/databaseConfig');
const Patient = db.patients;
const PersonalInformation = db.personalInformation;
PersonalInformation.Patient = PersonalInformation.belongsTo(Patient);
exports.create = async (req, res) => {
try {
let payload = await req.body;
await console.log('Recevied request: CREATE /api/patients & payload: ', payload);
let newPatientEntry = Patient.create();
let newPInfo = await PersonalInformation.create({
...payload,
patient: newPatientEntry
}, {
include: [{
association: PersonalInformation.Patient,
}]
});
res.send(newPInfo);
} catch (e) {
console.log('error inside create method Patient controller');
throw new Error(e);
}
};
Instead of 1x patient entry and 1x personalInformation entry, the result is 2x patient entries 1x personalInformation. The personalInformation entry has a patient's uuid in the table (the latter of the 2 patients created). I don't know why there are two patient entries.
Here is the relevant nodejs log:
2018-12-05T01:17:57.644499+00:00 app[web.1]: Executing (default): INSERT INTO "patients" ("uuid","createdAt","updatedAt") VALUES ('89290b66-999d-4f10-96b3-4105a26a9450','2018-12-05 01:17:57.583 +00:00','2018-12-05 01:17:57.583 +00:00') RETURNING *;
2018-12-05T01:17:57.645703+00:00 app[web.1]: Executing (default): INSERT INTO "patients" ("uuid","createdAt","updatedAt") VALUES ('9ed075da-757a-457b-b939-ed7e4c7b523a','2018-12-05 01:17:57.612 +00:00','2018-12-05 01:17:57.612 +00:00') RETURNING *;
2018-12-05T01:17:57.659918+00:00 app[web.1]: Executing (default): INSERT INTO "personalInformations" ("id","nameTitle","nameFirst","nameMiddle","nameLast","nameSuffix","nameAlias","dateOfBirth","sex","gender","occupation","deceased","createdAt","updatedAt","patientUuid") VALUES (DEFAULT,'Mr','Robert','Swan','Mueller','II','Bob','1950-12-15 00:00:00.000 +00:00','Male','Man','Special Counsel','False','2018-12-05 01:17:57.594 +00:00','2018-12-05 01:17:57.594 +00:00','9ed075da-757a-457b-b939-ed7e4c7b523a') RETURNING *;
The models are structured as follows:
// patient.model.js
const uuid = require('uuid/v4');
module.exports = (sequelize, Sequelize) => {
const Patient = sequelize.define('patient', {
uuid: {
primaryKey: true,
allowNull: false,
type: Sequelize.UUID,
defaultValue: () => uuid(),
}
});
return Patient;
};
and
// personalInformation.model.js
module.exports = (sequelize, Sequelize) => {
const PersonalInformation = sequelize.define('personalInformation', {
nameFirst: {
type: Sequelize.STRING,
notEmpty: true,
allowNull: false,
},
nameLast: {
type: Sequelize.STRING,
notEmpty: true,
allowNull: false,
},
... etc
... etc
});
return PersonalInformation;
}

Yes it will make 2 entries because you are creating it twice :
let newPatientEntry = Patient.create(); // <----- HERE
let newPInfo = await PersonalInformation.create({
...payload,
patient: newPatientEntry // <----- HERE
}, {
include: [{
association: PersonalInformation.Patient,
}]
});
You can try this :
// let newPatientEntry = Patient.create(); // <----- REMOVE THIS
let newPInfo = await PersonalInformation.create({
...payload,
patient: {} //<---- MAKE THIS BLANK
}, {
include: [{
association: PersonalInformation.Patient,
}]
});

Related

Sequelize insert multiple rows into MySQL table(NodeJS Problem)

I'm a beginer at NodeJS, I am Learning Sequelize framework and trying interactive with database. everything is okay until i'm writing insert into table function by sequelize model, Here is My cdoe:
const {Sequelize, DataTypes} = require("sequelize");
const sequelize = new Sequelize("task_management","root","Th#ng123",{
host : "localhost",
dialect : "mysql",
});
//Tao 1 sequelize model
const Task = sequelize.define(
"Task",
{
//Columns in table
name:{
type: Sequelize.STRING, //string
allowNull: false,
},
status: {
type : DataTypes.STRING, //STRING
}
}
)
//Synchronus function <=> Create a new Table in database
const syncModel = async ()=>{
await Task.sync({force: true});
console.log("Task sync model complete");
}
// syncModel();
const createTask = async () => {
// c1
const newTask = Task.build({ name: "Learning NodeJS", status: "OPEN" });
await newTask.save();
// c2
const golangTask = await Task.create({
name: "Learning Golang",
status: "OPEN",
});
};
createTask();
// Check connection
const checkConnect = async ()=>{
try {
await sequelize.authenticate();
console.log("Task check connect complete");
} catch (error) {
console.error("Unable connect Database")
}
}
But the result is with each Create code, in database inserted 3 rows. Like this
enter image description here
What happen and what i can do with this case ? Tell me please
Thank you!

How to push data with Mongoose to a nested array in MongoDB

I'm trying to push data to a nested array in mongodb. I'm using mongoose as well.
This is just mock code to see if i can get it working:
User model:
import mongoose from "mongoose";
const CoinSchema = new mongoose.Schema({
coinID: { type: String },
});
const CoinsSchema = new mongoose.Schema({
coin: [CoinSchema],
});
const WatchlistSchema = new mongoose.Schema({
watchlistName: { type: String },
coins: [CoinsSchema],
});
const NameSchema = new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
username: { type: String },
});
const UserSchema = new mongoose.Schema({
name: [NameSchema],
watchlists: [WatchlistSchema],
test: String,
});
const User = mongoose.model("User", UserSchema);
export default User;
route:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
const updatedUser = await User.findByIdAndUpdate(id, {
$push: { "watchlists[0].coins[0].coin": newCoin },
});
await updatedUser.save();
// console.dir(updatedUser, { depth: null });
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});
request.body // "coinID": "test"
I've tried a lot of different ways to push this data but still no luck. I still get 201 status codes in my terminal which indicates something has been pushed to the DB, but when I check nothing new is there.
Whats the correct way to target nested arrays and push data to them?
It's not perfect but you could get the user document, update the user's watchlist, and then save the updated watchlist like so:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
// get the user
let user = await User.findById(id);
// push the new coin to the User's watchlist
user.watchlists[0].coins[0].coin.push(newCoin);
//update the user document
const updatedUser = await User.findOneAndUpdate({ _id: id },
{
watchlists: user.watchlists,
},
{
new: true,
useFindAndModify: false
}
);
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});

Sequelize associations between two tables

I am fairly new to this (using sequelize) and everything is new to me. The thing is that I can create and get users through my "users.model.js" but now I want to create a model called "data.model.js" to associate some data to a certain user.
So according to the sequelize docs, my associations should be the following:
Users.hasMany(Data)
Data.belongsTo(Users)
But when sequelize creates my tables, I don't have my foreign key in my data table.
I will share my code with you:
config file (config.js):
const Sequelize = require('sequelize');
const connection = new Sequelize('drglicemia', 'root', '', {
host: 'localhost',
dialect: 'mysql'
});
module.exports = connection;
data.model.js:
const sequelize = require('sequelize');
const db = require('../config/database');
const usersTable = require('./users.model')
let Data = db.define('tabeladados', {
dta: { type: sequelize.DATEONLY },
hora: { type: sequelize.DATE },
indiceglicemia: { type: sequelize.STRING },
insulina: { type: sequelize.STRING },
medicacao: { type: sequelize.STRING },
}, {
timeStamps: false, tableName: 'tabeladados'
});
//associates the dataTable table with the users
Data.associate = () => {
Data.belongsTo(usersTable)
}
module.exports = Data;
users.model.js:
const sequelize = require('sequelize');
const promise = require('bluebird')
const bcrypt = promise.promisifyAll(require('bcrypt'))
const db = require('../config/database');
const dataTable = require('./data.model')
let Users = db.define('utilizadores', {
username: { type: sequelize.STRING },
email: { type: sequelize.STRING },
password: { type: sequelize.STRING },
}, {
timeStamps: false, tableName: 'utilizadores',
});
//encrypts the password before submiting to the database
Users.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
//validates the password submited by the user with the one encrypted in the database
Users.prototype.validPassword = async (password) => {
return await bcrypt.compare(password, this.password);
}
//associates the users table with the dataTable
Users.associate = () => {
Users.hasMany(dataTable)
}
module.exports = Users;
I believe that when I am trying to associate my tables I am doing something wrong, because I feel that I am doing it the wrong way.
I don't know but everything works besides this.
But it's like what I said in the beginning, I am new to sequelize xD
I think the reason is circular reference. user.model.js requires data.model.js, and data.model.js requires user.model.js.
You need to create an index.js file. Require and make the associations for all models here, then re-export them. E.g.
./models/index.js:
const User = require('./user.model.js');
const Data = require('./data.model.js');
User.hasMany(Data);
Data.belongsTo(User);
module.exports = {User, Data}
service.js or controller.js:
const models = require('./models/index.js');
// use models
await models.User.findAll();
Remove below codes in your model file:
// Remove from user.model.js file
Users.associate = () => {
Users.hasMany(dataTable)
}
// Remove from data.model.js file
Data.associate = () => {
Data.belongsTo(usersTable)
}

Sequelize - Many to Many relationship Model A is not associated to Model B

I have two Entities: TrainingDay and Exercise which are in a many to many relationship. For the implementation of the relationship I have oriented myself on the following link: https://medium.com/#the_ozmic/how-to-create-many-to-many-relationship-using-sequelize-orm-postgres-on-express-677753a3edb5.
Unfortunately, I get the following error: Unhandled rejection SequelizeEagerLoadingError: TrainingDays is not associated to Exercises!
Exercises.js
//jshint esversion:6
const Sequelize = require('sequelize');
const database = require('../database.js');
const TrainingDays = require('./TrainingDays.js');
const Exercises = database.define('Exercises', {
id: {
type: Sequelize.INTEGER,
primaryKey: true
},
name: Sequelize.STRING,
description: Sequelize.STRING
});
// TODO: not shure why I have to wrap Exercise.belongsToMany... into Exercise.associate = function(models) {...
Exercises.associate = function(models) {
Exercises.belongsToMany(models.TrainingDays, {
through: 'ExerciseTrainingDays',
as: 'trainingDays',
foreignKey: 'exerciseId'
});
};
module.exports = Exercises;
TrainingDay.js
//jshint esversion:6
const Sequelize = require('sequelize');
const database = require('../database.js');
const TrainingPlans = require('./TrainingPlans.js');
const Exercises = require('./Exercises.js');
const TrainingDays = database.define('TrainingDays', {
id: {
type: Sequelize.INTEGER,
primaryKey: true
},
date: Sequelize.DATE,
muscleGroup: Sequelize.STRING
});
TrainingDays.associate= function(models){
TrainingDays.belongsTo(models.TrainingPlans);
TrainingDays.belongsToMany(models.Exercises, {
through: 'ExerciseTrainingDays',
as: 'exercises',
foreignKey: 'trainingDayId'
});
};
module.exports = TrainingDays;
Here is the Join Entity:
ExerciseTrainingDays.js
//jshint esversion:6
const Sequelize = require('sequelize');
const database = require('../database.js');
const ExerciseTrainingDays = database.define('ExerciseTrainingDays', {
ExerciseId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'Exercises',
key: 'id'
}
},
TrainingDayId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'TrainingDays',
key: 'id'
}
}
});
module.exports = ExerciseTrainingDays;
I use the following code for testing:
//jshint esversion:6
const TrainingPlans = require('./models/TrainingPlans.js');
const TrainingDays = require('./models/TrainingDays.js');
const Exercises = require('./models/Exercises.js');
const Sets = require('./models/Sets.js');
const ExerciseTrainingDays = require('./models/ExerciseTrainingDays.js');
const database = require('./database.js');
database.sync();
TrainingPlans.findAll().then(trainingPlans => {
console.log("All trainingPlans:", JSON.stringify(trainingPlans, null, 4));
});
TrainingDays.findAll().then(trainingDays => {
console.log("All trainingDays:", JSON.stringify(trainingDays, null, 4));
});
Exercises.findAll().then(exercises => {
console.log("All exercises:", JSON.stringify(exercises, null, 4));
});
Exercises.findAll({
include:[{
model: TrainingDays,
where: {id : 1000}}]
}).then(exercise => {
console.log("All exercises:", JSON.stringify(exercise, null, 4));
});
After the call of Exercises.findAll({ include:[{… I get the described error. The other queries work in a proper way. I don't know what I'm doing wrong, I hope someone can help me.

Mongoose .Populate() returns empty array

I do not understand what the problem is.
And why each element from the 'tasks' array is null.
Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
tasks: [{type: Schema.Types.ObjectId, ref: 'Task'}]
}
);
const taskSchema = new Schema({
title: String
});
const User = mongoose.model('User', userSchema);
const Task = mongoose.model('Task', taskSchema);
// Add some default to DB
const task1 = new Task({
title: "Welcome! Here You Can:"
});
const task2 = new Task({
title: "ADD EDIT DELETE SHARE your TASKS "
});
const defaultTasks = [task1, task2];
When create new User I Add defaultTasks
const newUser = {
email: req.body.email,
password: req.body.password,
tasks: defaultTasks
};
Get Users Tasks
app.get('/tasks/', function(req, res){
const email = req.query.user;
User
.findOne({email: email})
.populate('tasks')
.exec()
.then(foundUser => {
console.log(foundUser);
const data = [];
Object.keys(foundUser.tasks).forEach(function(key) {
const val = foundUser.tasks[key];
data.push([val.title, val._id]);
});
res.send(data);
console.log('Data to send ' + data);
});
});
Before .Populate() console.log {
{ tasks: [ 5cf78ac1d08ee617fc89f7ed, 5cf78ac1d08ee617fc89f7ee ]
After { { tasks: [],
Please Help! All that I found did not solve my problem.
Maybe problem in defaultTasks. But i dont see it.
Your code doesn't save your task to DB, it just creates an object. So later when you populate User there are no tasks in DB to be found.
const task1 = await new Task({
title: "Welcome! Here You Can:"
}).save();
// or
const task1 = await Task.create({
title: "Welcome! Here You Can:"
});
P.s. of course you can deal with asynchronous calls the way you want.

Categories