Sequelize update with association not updating table for the associated model - javascript

I have two tables below:
1. Poll
2. Option
The Poll model is as follows:
const Sequelize = require('sequelize');
let dbService = require('../services/dbService.js');
let Option = require('./options');
let Poll = dbService.define('Poll', {
poll: {
type: Sequelize.STRING,
allowNull: false
},
isAnonymous: {
type: Sequelize.STRING,
allowNull: false
},
startDate: {
type: Sequelize.STRING,
},
endDate: {
type: Sequelize.STRING,
},
active: {
type: Sequelize.BOOLEAN,
}
});
Poll.hasMany(Option);
module.exports = Poll;
The Option model is as follows:
const Sequelize = require('sequelize');
let dbService = require('../services/dbService.js');
let Option = dbService.define("option", {
name: Sequelize.STRING
});
module.exports = Option;
This is my /GET route for api/poll/:id
I want to update the poll. All the other routes are working fine. I am just stuck on updating the model.
The controller for /PUT api/poll/:id
The service for /PUT api/poll/:id
This only updates the Poll table, the Option table's column does not get updated. How can I achieve the update with the one to many association like this?
I have tried this too! Sequelize update with association
I have even done the same as the sequelize docs. But I am unable to achieve what I want. I've been stuck on this for a while. Any kinda help will be appreciated.
Thanks!

For update you can try SequelizeModel.upsert() function.

Related

how to use find function in nodejs

const categorySchema = mongoose.Schema({
name: {
required: true,
type: String
}
});
const productSchema = mongoose.Schema({
name: {
type: String,
required: true
},
category: {
type: mongoose.Schema.Types.Mixed,
ref: "Category",
required: true
}
});
As you see above I have two models where I am using Category inside Product.
Now I want to fetch all the products by passing a particular Category or its id as _id which gets generated by default by mongodb.
Although I am achieving the desired result do this below:
const id = req.query.categoryId;//getting this from GET REQUEST
let tempProducts = [];
let products = await Product.find({});
products.forEach(product => {
if (product.category._id===id){
tempProducts.push(product);
}
});
It gets me what I want to achieve but still I want to know how to get it using "find" function. or this what I am doing is the only way.
Ok thank you all for your time. I found out the solution which is:
First of all below is my schema as Product which includes another schema named Category:
const productSchema = mongoose.Schema({
name: { type: String, required: true },
category: { type: mongoose.Schema.Types.Mixed, ref: "Category", required: true } });
And to get all the products related to a particular category,
We need to add our query inside quotes like this:
let tempProducts = [];
tempProducts = await Product.find({ "category._id": id});
This is how I achieved as I wanted and working as expected.

How to use Sequelize associations with .then in controller

This is my ToWatch Model in toWatch-model.js file which in code has UserModel->ToWatch 1:1 relationship and has ToWatch->MovieModel 1:M relationship.
const Sequelize = require('sequelize');
const sequelize = require('./../common/db-config');
const MovieModel = require ("./movie-model");
const UserModel = require("./user-model");
const Model = Sequelize.Model;
class ToWatch extends Model{}
ToWatch.init({
id: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id_towatch'
},
date: {
type: Sequelize.DATE,
allowNull: false,
field: 'date'
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
field: 'id_user',
references:{
model: UserModel,
key: "id"
}
},
movieId: {
type: Sequelize.INTEGER,
allowNull: false,
field: 'movie_id_towatch',
references:{
model: MovieModel,
key: "id"
}
},
},
{
sequelize,
modelName: 'towatch',
tableName: 'towatch',
timestamps: false
// options
});
//Here is the relation ************
UserModel.hasOne(ToWatch, {
foreignKey: {
type:Sequelize.DataTypes.INTEGER,
allowNull:false,
name:'fk_foreign_key_towatch'
}
});
ToWatch.belongsTo(UserModel);
ToWatch.hasMany(MovieModel, {
foreignKey: {
type:Sequelize.DataTypes.INTEGER,
allowNull:false,
name:'movie_id_towatch'
}
});
MovieModel.belongsTo(ToWatch);
module.exports = ToWatch;
I watched many tutorials, but being my first time trying to make a method that will return everything including something from my other table via ID, I wasn't sure where to put and how to put data that I need in this method, considering it has .then(data=>res.send). Tutorials were doing it other ways by fetching or using async-await, and even documentation didn't help me here. Can somebody tell me what to put and where inside this method, that is inside toWatch-controller.js file for me being able to see let's say all the movie data (title,img,date) ,as an array I think, of the getToWatch method.
const ToWatch = require('./../models/toWatch-model');
module.exports.getToWatch = (req,res) => {
ToWatch.findAll().then(toWatch => {
[WHAT DO I PUT HERE?]
res.send(toWatch);
}).catch(err => {
res.send({
status: -1,
error:err
})
})
}
I need something like this ToWatch{
color:red,
cinema:"MoviePlace",
movieId{title:"Anabel", img:"URL", date:1999.02.23}
As I understood your question right, what you trying to do is return toWatch model instances with including User and Movie models.
To do so you can pass options in findAll() method like below:
ToWatch.findAll({include: [{model: User}, {model: Movie}]})... //and rest of your code
Or alternatively to keep your code clean you can use scopes:
// below the toWatch-model.js file
ToWatch.addScope('userIncluded', {include: {model: User}})
ToWatch.addScope('movieIncluded', {include: {model: Movie}})
And in the getToWatch method:
// you can pass several scopes inside scopes method, its usefull when you want to combine query options
ToWatch.scopes('userIncluded', 'movieIncluded').findAll()... //rest of your code
For more information check out sequelize docs

Sequelize allow null set to false on foreign key

Here is the code below for one of my tables
const { Model, DataTypes } = require('sequelize');
const Algorithm = require('./algorithm');
const Exchange = require('./exchange');
const User = require('./user');
//#JA - This model defines the api keys for each user's exchange
//#JA - For security reasons in case the database gets hacked the keys will be stored using encryption.
module.exports = function(sequelize){
class AlgorithmRule extends Model {}
AlgorithmModel = Algorithm(sequelize);//#JA - Gets a initialized version of Algorithm class
ExchangeModel = Exchange(sequelize);//#JA - Gets initialized version of the Exchange class
UserModel = User(sequelize);//#JA - Gets a initialized version of User class
var AlgorithmRuleFrame = AlgorithmRule.init({
algorithm_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: AlgorithmModel,
key: 'id',
}
},
exchange_id: {
type: DataTypes.STRING,
references: {
model: ExchangeModel,
key: 'name',
},
},
user_id: {
type: DataTypes.INTEGER,
references: {
model: UserModel,
key: 'id',
},
},
type : { //Partial-Canceled implies that the order was partially filled and then canceled.
type: DataTypes.ENUM('Percent Of Equity','Cash'),
allowNull: false,
defaultValue: 'Percent Of Equity'
},
type_value: { //#JA - This will be either treated as a percentage or 'cash' value for the type chosen for the algorithm.
type: DataTypes.DECIMAL(20,18),
allowNull: false
},
}, {
sequelize,
modelName: 'AlgorithmRule',
indexes: [{ unique: true, fields: ['algorithm_id','exchange_id','user_id'] }]
});
return AlgorithmRuleFrame
};
I'm trying to set this up so that I can allownull:false on algorithm_id and exchange_id and user_id. I want it so there HAS to be values there for any records to be allowed.
I can't even get allowNull:false manually through the database itself. So my first question is, is this even possible?
If it is, how do I do it with sequelize?
I can use the typical hasOne() with foreign key commands because then I can't create a composite unique of the foreign keys. The only way I was able to do this was the way I did using the references: json structure.
How do I allownull:false for a foreignKey reference defined the way I have it?
To be clear something like this will NOT work
Task.belongsTo(User, { foreignKey: { allowNull: false }, onDelete: 'CASCADE' })
This will NOT work because I'm using a composite unique key across 3 foreign keys and in order to do that I need reference to it's name and that is not possible unless it's defined on the table before these commands above our input. Hopefully this makes sense.
Any help is greatly appreciated!
Okay so apparently
algorithm_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: AlgorithmModel,
key: 'id',
}
},
This code is correct. HOWEVER, if you created the database already and the foreign key was already defined it will NOT change the allowNull via the alter command. You have to COMPLETELY drop the table and THEN it will allow the allowNull:false attribute to work.
This threw me for a loop for a long time, so I help this saves someone else a lot of frustration.

Mongoose One to Many relatioship

I'm trying to create a one to many relationship between Category and Services models.
I have two schemas: Category and Service.
Category schema holds services array.
Service schema hold category _id.
I'm trying to retrieve all Categories including services.
Category schema:
import mongoose from 'mongoose';
const categoriesModel = new mongoose.Schema(
{
category: {
type: String,
required: true,
},
services: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'Service' }],
},
{ timestamps: true }
);
export const Category = mongoose.model('Category', categoriesModel);
Service schema:
import mongoose from 'mongoose';
const serviceSchema = new mongoose.Schema(
{
serviceName: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
images: {
type: Array,
image: Buffer,
required: true,
},
category: {
type: mongoose.SchemaTypes.ObjectId,
ref: 'Category',
required: true,
},
},
{ timestamps: true }
);
export const Service = mongoose.model('Service', serviceSchema);
HTTP get request to retrieve all Categories including Services:
export const getAllCategories = async (req, res) => {
try {
const docs = await Category.find({}).populate({
path: 'services',
model: 'Service',
});
console.log(docs);
res.status(200).json({ data: docs });
} catch (err) {
res.status(400).json(err.message);
}
};
This is what I get as a response from the request above:
{
"services": [],
"_id": "60affe06c71901281d3d820d",
"category": "Electricity"
},
I've tried different ways to populate services but none of them worked.
What I've tried so far:
Add additional nesting to services attribute.
Adding object to the populate params:
{
path: 'services',
model: 'Service',
}
Removing existing data ant posting additional one.
Fun fact. Retrieving each Service individually, service data includes the actual category, that it's been assigned to:
export const getAllServices = async (req, res) => {
try {
const doc = await Service.find({}).populate('category');
res.status(200).json({ data: doc });
} catch (err) {
res.status(400).json(err);
}
};
Is there something I'm missing regarding including services within retrieving categories? It's really interesting, because somehow the actual services data is [].
EDIT: Each category in Categories collection has empty services array. The services are added dynamically, they might be null for specific category until user adds a service and assigns a category to it. Is this forbidden? Do I need to find specific category and add a specific service to category while creating new service? If yes, this would require to add additional Category model to the services.controller.js and find the category. Is this really an appropriate solution?

Mongoose autopopulate on create

I'm using the mongoose plugin autopopulate to populate docs from a separate collection. Here's a dumbed down schema:
const PostSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true,
autopopulate: {
select: ['firstName', 'lastName', 'email', 'username']
}
},
comment: { type: String }
}
)
Now, when I create a post with
const post = await Post.create({ user, comment });
It returns null for the populated user even though it shows up in the database and subsequent queries. I've used the { new: true } option on findByIdAndUpdate but it doesn't seem to work on create. Any thoughts on how to get create to return the populated docs?

Categories

Resources