This is the parent model/table:
const { Sequelize, DataTypes } = require('sequelize');
const VerifyToken = require('./verifyToken');
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
password: DataTypes.STRING,
email: DataTypes.STRING,
}, {
tableName: 'users',
timestamps: false,
//syncOnAssociation: true
hierarchy: true,
underscored: true
});
User.associate = function (models) {
const {VerifyToken} = models;
User.hasOne(VerifyToken, {
as: 'verify_tokens',
foreign_key: 'user_id'
});
};
return User;
};
This is the child model:
const User = require('./user');
module.exports = (sequelize, DataTypes) => {
const VerifyToken = sequelize.define('VerifyToken', {
user_id: DataTypes.INTEGER,
token: DataTypes.STRING,
}, {
tableName: 'verify_tokens',
hierarchy: true,
underscored: true
});
VerifyToken.associations = function (models) {
const {User} = models;
VerifyToken.belongsTo(User);
};
return VerifyToken;
};
models/index.js file:
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
, but when I make a query like this:
const verifyToken = await models.VerifyToken.findOne({
where: {
token
},
include:{
model: models.User
}
});
I am getting this:
SequelizeEagerLoadingError: User is not associated to VerifyToken!
Please correct VerifyToken.associations with VerifyToken.associate
Remove a redundant import of const VerifyToken = require('./verifyToken'); from the User model definition.
Related
When I'm uploading data about my new user I don't get any information back with the new json file where is saved my user, I only get '{}' and that's all. I'm sending here my code and what I get in Postman.
index.js
const express = require('express');
const app = express();
const dotenv = require('dotenv');
dotenv.config();
const userRoute = require("./routes/user");
const authRoute = require("./routes/auth");
const mongoose = require('mongoose');
const { CLIENT_RENEG_LIMIT } = require('tls');
const { application } = require('express');
mongoose
.connect(process.env.MONGO_URL)
.then(() => console.log('Connected to Mongoose server'))
.catch((err) => {
console.log(err);
});
app.use(express.json());
app.use('/api/users', userRoute);
app.use('/api/auth', authRoute);
app.listen(process.env.PORT || 5200, ()=>{
console.log('Listening on port 5200');
});
auth.js
const router = require('express').Router();
const user = require('../models/user');
//REJESTRACJA
router.post('/rejestracja', async (req, res)=>{
const newUser = new user({
username: req.body.username,
email: req.body.email,
password: req.body.password,
});
try{
const saveduser = newUser.save();
res.status(201).json(saveduser);
}catch(err){
res.status(500).json(err);
}
});
module.exports = router
user.js
const mongoose = require('mongoose');
const {Boolean} = require('webidl-conversions');
const UserSchema = new mongoose.Schema({
username: { type: 'string', unique: true, required: true},
email: { type: 'string', unique: true, required: true},
password: { type: 'string', required: true, unique: true},
admin: { type: 'Boolean', default: false},},
{timestamps: true}
)
module.exports = mongoose.model('User', UserSchema);
postman screenshot
I am working with Express JS and Sequelize which is connected to a MSSQL database. I am unable to perform any requests as I am getting the error "Cannot read properties of undefined (reading 'findAll')". Can anyone help out with this one?
Below is my set up:
Invites Model:
module.exports = (sequelize, DataTypes) => {
const Invites = sequelize.define("Invites", {
Id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
Recipient: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
Code: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: true
}
},
Score: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: true
}
},
Status: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
notEmpty: true
}
},
Created: {
type: DataTypes.DATE,
allowNull: false,
validate: {
notEmpty: true
}
},
ExpiresOn: {
type: DataTypes.DATE,
allowNull: false,
validate: {
notEmpty: true
}
}
});
return Invites;
};
inviteController:
const { invitesModel } = require('../models/Invites');
const getAllInvites = (req, res) => {
invitesModel.findAll().then((invites) => {
res.send(invites);
}).catch((err) => {
console.log(err);
})
};
module.exports = {
getAllInvites,
}
index.js:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
require('dotenv').config();
const db = require('./models');
const invitesController = require('./controllers/inviteController');
const cookieParser = require('cookie-parser');
const PORT = process.env.PORT || 5000;
app.use(cors()); //Cross origin resource sharing
app.use(express.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
//Get invite data
app.route('/api/invites').get(invitesController.getAllInvites);
db.sequelize.sync().then((req) => {
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
});
/models/index.js:
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
The require statement '../models/Invites' does not return an object with an invitesModel property.
You probably want to change your import statement to:
const { Invites } = require('../models');
And then use
Invites.findAll(...);
to query the Invites model.
If you're not sure what a require statement is grabbing, you can add a log statement to check:
const modelsObj = require('../models');
console.log(Object.keys(modelObj); // or console.log(JSON.stringify(modelsObj);
try add '?'
const getAllInvites = (req, res) => {
invitesModel?.findAll()?.then((invites) => {
res.send(invites);
}).catch((err) => {
console.log(err);
})
};
I am creating a post request that adds new posts to MongoDB. The post request works well and I can see the post in Mongo.
I am struggling at accessing properties from the object using req.body, specifically req.body._id. I would like to console.log the req.body._id to verify that it worked. In the terminal, I keep on getting 'undefined'.
All the solutions I have seen so far say include app.use(express.json()); and app.use(express.urlencoded({ extended: false })); which I have.
I am stumped on what to try next. Any suggestions would be appreciated.
Here is my server.js file
const express = require('express');
const dotenv = require("dotenv").config();
const mongoose = require('./db/mongoose');
const app = express();
const postsRoute = require('./routes/posts');
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/posts", postsRoute);
app.listen( process.env.PORT || 5000, (err) => {
console.log(`listening on port ${process.env.PORT}`);
});
Here is my routes file
const express = require('express');
const router = express.Router();
const { allPosts, createPost } = require('../db/models/postModel');
router.get("/", async (req, res) => {
console.log(`req.title is: ${req.title}`);
try {
const posts = await allPosts();
res.send(posts);
} catch (err) {
console.log(err.message);
}
});
router.post("/create", async (req, res) => {
const newPost = req.body;
try {
const addingPost = await createPost(newPost);
console.log(`req.body is:${addingPost}`);
console.log(`req.body title:${addingPost.title}`);
console.log(`addingPost is: ${addingPost} with id of ${addingPost._id}`);
res.send (addingPost);
} catch (err) {
res.status(500).send(err.message);
}
});
module.exports = router;
Here is my Schema file
const mongoose = require('mongoose');
const { Schema } = mongoose;
const postSchema = new Schema({
author: {
type: String,
required: true
},
title: {
type: String,
required: true
},
content: {
type: String,
required: true,
},
tags: [String],
file: String,
likes: {
type: Number,
//We want to default to 0 likes
default: 0,
},
createdAt: {
type: Date,
default: new Date(),
},
});
const postModel = mongoose.model('Post', postSchema);
//Get all posts
const allPosts = async () => {
const posts = await postModel.find();
return posts;
};
//Create posts
const createPost = async (post) => {
const newPost = await postModel.create(post);
return newPost;
};
module.exports = { allPosts, createPost };
Console.log outputs in the Node REPL
I have included a picture showing what the console.log ouputs in the terminal. Hopefully this supports my question.
Is it okay if I make models from copy-pasting? For instance, I made my first model User through Sequelize's model:generate. And then for other models, I just copy-pasted everything from the User model to my new models.
When doing db sync:
db.sequelize.sync({ force : true}).then(() => {
console.log("Drop and re-sync db.")
})
The new models won't create new tables. So I'm thinking copy-pasting for new models won't work. Is this right?
User model:
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
id: { type: DataTypes.BIGINT, allowNull: false, unique: true, primaryKey: true },
fbid: { type: DataTypes.BIGINT, allowNull: false, unique: true },
email: DataTypes.STRING,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
photo_url: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
And generated from copy-paste + modification of user model, I have: Country model
'use strict';
module.exports = (sequelize, DataTypes) => {
const Country = sequelize.define('Country', {
country_name: DataTypes.STRING
}, {});
Country.associate = function(models) {
// associations can be defined here
};
return Country;
};
Index.js generated by the cli in my models:
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Then after the generated models, after executing model:generate I transferred the generated User.js into a User folder. Then do the copy-paste, not sure if moving the files affect the registering of the models I created by copy-paste.
Based on the comments above, I realized that my index.js file (generated by Sequelize) wasn't looking for model files that ARE placed in subfolders. Instead, it ONLY looks for the model files that are in the root folder - same level of the index.js file.
So I posted this question: Javascript get all files in a folder that are inside another fold
I had to use the package glob to make the index.js file look for subfolders too.
So my index.js's content is now:
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config')[env];
const db = {};
const glob = require("glob")
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
const files = glob.sync(__dirname + "/*/*.js")
files.forEach(file => {
const model = sequelize['import'](file);
db[model.name] = model;
})
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
To answer the specific question, NO. I don't have to do the commands all the time. I can copy-paste-edit new models instead.
In expressJs project, I try to use sequelize to interact with database.
This is my model/user.js :
module.exports = (sequelize, DataTypes) => {
sequelize.define('user', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
})
}
And this is models/index.js :
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.db.database,
config.db.user,
config.db.password,
config.db.options
)
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
var a = path.join(__dirname, file);
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
The problem is in this line
const model = sequelize.import(path.join(__dirname, file));
Which returns undefine to model variable.
What did I miss here? I appreciate any hint?
Whole code on Github : here
Problem could be because of a missing return
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', { // Missing return
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
})
}
Change to
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
});
return User;
}