I have the following two files running on an Express Node.js server:
home.js
var express = require('express')
var sequelize = require('sequelize')
var db = require('../../shared/db.js')
var op = sequelize.Op
var router = express.Router()
router.get('/home', function(req, res, next) {
db.shared.person.findAll({
where: {
email: {
[op.ne]: null
}
},
order: ['id']
}).then(function (person) {
res.locals = {
person: person
}
res.render('home')
})
})
module.exports = router
db.js
var sequelize = require('sequelize')
var config = {
host: 'localhost',
port: 5432,
username: '...',
password: '...',
database: 'postgres',
dialect: 'postgres',
operatorsAliases: false
}
var db = new sequelize(config)
module.exports = {
shared: {
person: db.define('person', {
id: {
type: sequelize.INTEGER,
primaryKey: true
},
name: sequelize.STRING,
email: sequelize.INTEGER
}, { freezeTableName: true , timestamps: false, schema: 'shared' }),
}
}
When I try to run this query, I get an error claiming Unhandled rejection Error: Invalid value { [Symbol(ne)]: null }
What am I doing wrong? I can use $ne and even ne just fine but they've been deprecated and are not entirely safe to use. Furthermore, it's not just [op.ne] - I get this error when I use any conditional like this.
I'm basing this all on this guide so I'm not really sure what I could be doing wrong here.
Unhandled rejection Error: Invalid value might also appear if you didn't setup string aliases like this:
const Op = Sequelize.Op;
const operatorsAliases = {
$eq: Op.eq,
$ne: Op.ne,
...
$any: Op.any,
$all: Op.all,
$values: Op.values,
$col: Op.col
};
const connection = new Sequelize(db, user, pass, { operatorsAliases });
But, better to remove String based aliases from code and use [Op.ne] for example, Sequlize is planning to deprecate them soon.
Sequelize instance in both db.js and home.js are different, this is because node caches a required module based on it path.
To solve this issue you can pass around correct instance in db.js
module.exports = {
shared: {
person: db.define('person', {
id: {
type: sequelize.INTEGER,
primaryKey: true
},
name: sequelize.STRING,
email: sequelize.INTEGER
}, { freezeTableName: true , timestamps: false, schema: 'shared' }),
},
db: db
}
Then finally use operators from that shared instance to do query
var express = require('express')
var sequelize = require('sequelize')
var db = require('../../shared/db.js')
var op = db.db.Op;
var router = express.Router()
router.get('/home', function(req, res, next) {
db.shared.person.findAll({
where: {
email: {
[op.ne]: null
}
},
order: ['id']
}).then(function (person) {
res.locals = {
person: person
}
res.render('home')
})
})
module.exports = router
One more thing, string operators are completely safe to use if you properly sanitize your user inputs. You only need to use secure operators if you are passing un-sanitized user input to Sequelize methods.
More on this topic
http://docs.sequelizejs.com/manual/tutorial/querying.html#operators-security
https://github.com/sequelize/sequelize/issues/8417
Related
I just start learning how to build a database by using
Im trying to add data to mongoDB and using the .findOne function, but I'm getting this error. is findOne a function in MongoDB?
My Goal is to try to build a full stack mobile application and using mongoDB for database. FrontEnd is flutter. I'm trying to send data from flutter to mongoDB using socket.io.
You might ask yourself why I'm using socket.io if I just need to save data to MongoDB. Well, The application building is a game where multiple users can Join a room and interact with each other.
Here is the versions that using to build the backend "mongoose": "^6.3.3", "socket.io": "^2.3.0"
TypeError: Room.findOne is not a function
at Socket.<anonymous> (/Users/Paul/Documents/server/Index.js:27:45)
at Socket.emit (node:events:390:28)
at /Users/Paul/Documents/server/node_modules/socket.io/lib/socket.js:528:12
at processTicksAndRejections (node:internal/process/task_queues:78:11)
Index.js
Here is my main file
const express = require("express");
var http = require("http")
const app = express();
const port = process.env.PORT || 3000;
var server = http.createServer(app);
const mongoose = require("mongoose");
const Room = require('./models/Room');
//adding socket IO and passing the variable server to it.
var io = require("socket.io")(server);
//middleware
app.use(express.json());
//connecting to MongoDB
const DB = 'mongodb+srv://user:1111#cluster0.tllj9.mongodb.net/?retryWrites=true&w=majority';
mongoose.connect(DB).then(() => {
console.log('Connection Successful!');
}).catch((e) =>{
console.log(e);
})
io.on('connection', (socket) => {
console.log('connected!');
socket.on('create-game', async({nickname, name, numRounds, occupancy}) => {
try {
const existingRoom = await Room.findOne({name});
if(existingRoom){
socket.emit('notCorrectGame', 'Room with that name already exists!');
return;
}
let room = new Room();
const word = getWord();
room.word = word;
room.roomName = roomName;
room.occupnacy = occupnacy;
room.numRounds = numRounds;
let player = {
socketID: socket.id,
nickname,
isPartyLeader: true,
}
room.players.push(player);
room = await room.save();
socket.join(room);
io.to(roomName).emit('updateRoom', room);
} catch (error) {
console.log(error);
}
})
})
server.listen(port, "0.0.0.0", () => {
console.log('Server started and running on port ' + port);
})
Player.js
const mongoose = require('mongoose');
const PlayerSchema = new mongoose.Schema({
nickname: {
type: String,
trim: true,
},
socketID: {
type: String,
},
isPartyLeader: {
type: Boolean,
default: false,
},
points: {
type: Number,
default: 0,
}
})
const playermodel = mongoose.model('Player', PlayerSchema);
module.exports = {playermodel, PlayerSchema}
Room.js
const mongoose = require("mongoose");
const { PlayerSchema } = require("./Player");
var roomSchema = new mongoose.Schema({
word: {
required: true,
type: String,
},
name: {
required: true,
type: String,
unique: true,
trim: true,
},
occupancy: {
required: true,
type: Number,
default: 4
},
maxRounds: {
required: true,
type: Number,
},
currentRound: {
required: true,
type: Number,
default: 1,
},
players: [PlayerSchema],
isJoin: {
type: Boolean,
default: true,
},
turn: PlayerSchema,
turnIndex: {
type: Number,
default: 0
}
});
const gameModel = new mongoose.model('Room', roomSchema);
module.exports = {gameModel, roomSchema};
I honestly can't figure out why I am encountering this error. Maybe, I just need a second eyes to help me out.
Can anyone help with this error? Please and Thank you in advance!
Your error is located here:
io.on('connection', (socket) => {
console.log('connected!');
socket.on('create-game', async({nickname, name, numRounds, occupancy}) => {
try {
//error is here
const existingRoom = await Room.findOne({name});
if(existingRoom){
socket.emit('notCorrectGame', 'Room with that name already exists!');
return;
}
Explanation:
Now, findOne is a function in mongoDB collection/mongoose model. This means const Room must be a collection for you to call Room.findOne()
However, according your index.js file, when you call Room, you aren't grabbing the mongodb collection/mongoose model.
const Room = require('./models/Room');
This is because the export from Room.js is {gameModel, roomSchema} and not just your model, which is what you should be calling the function off of, according to Mongoose documentation. Therefore, const Room = {gameModel, roomSchema}, which has no findOne() function
To fix:
Try object de-structuring the schema and model when you import it like so.
const {gameModel: Room, roomSchema} = require('./models/Room')
I'm using node.js with express and sequelize and my DB is mysql.
I tried to create a class model as written in the documentation: https://sequelize.org/master/manual/model-basics.html. I was able to connect to the DB, but couldn't figure out how to sync the model with the DB in order to create tables. here is my user model:
const { DataTypes, Model } = require('sequelize');
const connection = require("../server");
export class User extends Model { }
User.init({
id: {
type: DataTypes.BIGINT,
autoIncrement: true,
primaryKey: true,
unique: true,
allowNull: false
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
userType: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
connection
});
and here is my server.js:
const express = require("express");
const Sequelize = require("sequelize");
const app = express();
const port = 8080;
const connection = new Sequelize("coupons2", "root", "1234", {
host: "localhost",
dialect: "mysql"
})
connection.sync()
.then(() => {
console.log("Connection to DB was successful");
})
.catch(err => {
console.error("Unable to connect to DB", err);
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
})
module.exports = connection;
Thank you!
I think you forgot to require the Sequelize as shown in document you mentioned above
`const {Sequelize, DataTypes, Model } = require('sequelize');
and if you want that it table create automatically by models you can use sequelize.sync in your project
await sequelize.sync({ force: true });
console.log("All models were synchronized successfully.");
User.sync() - creates the table if it doesn't exist (and does nothing if it already exists)
User.sync({ force: true }) - creates the table, dropping it first if it already existed
User.sync({ alter: true }) - checks what is the current state of the table in the database (which columns it has, what are their data types, etc), and then performs the necessary changes in the table to make it match the model.
(async () => {
await sequelize.sync({ alter: true });
})();
I managed to create tables by importing the models to my server.js:
const models = require("./src/models/index");, and using the sync() method.
I have 3 sequelize models that i have defined imported into a file called sequelize.js like so:
const { Sequelize } = require("sequelize");
const UserModel = require("./models/user");
const ItemModel = require("./models/item");
const ReservationModel = require("./models/reservation");
const config = require("./dbconfig");
const db = config.database;
const Item = ItemModel(sequelize, Sequelize);
const User = UserModel(sequelize, Sequelize);
const Reservation = ReservationModel(sequelize, Sequelize);
Reservation.hasMany(Item);
Item.belongsTo(Reservation);
Reservation.belongsTo(User);
I then try to export them:
module.exports = { Item, User, Reservation };
However, when I try to access one of them and use a model function, I get an error.
const Model = require("../../sequelize");
const passport = require("passport");
module.exports = (app) => {
app.post("/registerUser", (req, res, next) => {
passport.authenticate("register", (err, user, info) => {
if (err) {
console.log(err);
}
if (info !== undefined) {
console.log(info.message);
res.send(info.message);
} else {
req.logIn(user, (err) => {
const data = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
username: user.email,
};
Model.User.findOne({
where: {
email: data.username,
},
}).then((user) => {
user
.update({
first_name: data.first_name,
last_name: data.last_name,
email: data.email,
})
.then(() => {
console.log("user created in db");
res.status(200).send({ message: "user created" });
});
});
});
}
})(req, res, next);
});
};
results in
TypeError: User.findOne is not a function
This is not an issue when I just export one of them.
module.exports = User;
const User = require("./sequelize");
...
User.findOne(...) //works
I've tried multiple ways of exporting, but none seem to work.
e.g
module.exports = {
Item: Item,
User: User,
Reservation: Reservation,
}
and
exports.Item = Item;
exports.User = User;
exports.Reservation = Reservation;
edit: Here is my user model for reference
module.exports = (sequelize, type) => {
return sequelize.define(
"user",
{
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
first_name: type.STRING,
last_name: type.STRING,
credentials: type.STRING,
email: {
type: type.STRING,
allowNull: false,
},
password: {
type: type.STRING,
allowNull: false,
},
},
{
tableName: "Users",
}
);
};
Why cant I export these multiple objects?
I have the exact structure you're using by importing all sequelize models into one file then module.exporting them in an object and the only thing I see thats different is how you define your models. I might be out of date but I learned as such:
const Sequelize = require('sequelize');
const db = require('../db');
module.exports = db.define('users', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
unique: true
},
}, {
timestamps: true,
});
Db declaration
const Sequelize = require('sequelize');
const db = new Sequelize(
process.env.DATABASE_URL, {
logging: false
}
);
module.exports = db;
Then your central import
const User = require('./user');
const Order = require('./order');
Order.belongsTo(User)
User.hasMany(Order)
module.exports = {
User,
Order
};
Then using it
const models = require('./models');
const results = await models.User.destroy({
where: {
id: id
}
});
if(results){
return results;
}
Found what was wrong. In my passport.js file, where I defined my localStrategy, I was doing an incorrect import.
My export in sequelize.js was
modules.export = {Item, User, Reservation};
while my import in passport.js was just
const User = require("../sequelize");
when it should have been
const Model = require("../sequelize");
const User = Model.User;
looks like I had it imported correctly in my signUp route, but not in my passport config file!
Error : usr.findOneAndUpdate is not a function
Model:
var mongoose = require('mongoose')
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt')
var schema = new Schema({
email: { type: String, require: true },
username: { type: String, require: true },
password: { type: String, require: true },
creation_dt: { type: String, require: true },
tasks:[{type:{type:String}}]
});
module.exports = mongoose.model('User',schema)
i want to Add some Task in tasks array so i use post method for That and code is
Code:
router.post('/newTask', function (req, res, next) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
var usr = new User(req.user)
usr.findOneAndUpdate(
{_id:req.user._id},
{$push:{tasks:dataa}}
)
try {
doc = usr.save();
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
})
i also read the documentation of findOneAndUpdate but i din't get solution please someone can Help out of this error....
Thank You.
You need to import your model into the file containing your routes. All mongoose methods are based off the schema that you define, not new instances you create.
For example, if you have a User model that looks like this:
// file is named user.js
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema ({
username: String,
password: String
})
module.exports = mongoose.model("User", userSchema)
You need to import the model so mongoose recognizes it as one
Like so (assuming the routes file and user model file are in the same directory):
const User = require("./user")
router.post("/newTask", (req, res) => {
User.findOneAndUpdate(//whatever you want to be updated)
})
I'm working on API project for client.
The problem is using POSTMAN when i hit POST method the status I get is Status: 500 TypeError.
I tried put some data to my DATABASE manually so that I can check if my CRUD method is working. The GET method is working fine.
This is the API route i created:
const express = require('express')
const Client = require('../../models/Client')
const router = express.Router()
// Get Client
router.get('/', (req, res) => {
Client.find()
.sort({date: -1})
.then(clients => res.json(clients))
.catch(err => res.status(404).json(err))
})
// Create Client
router
.post('/', (req, res) => {
const newClient = new Client({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
})
newClient
.save()
.then(client => res.json(client))
.catch(err => console.log(err))
})
module.exports = router
This is my Model:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const ClientSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
phone: {
type: String,
required: true,
},
created_at: {
type: Date,
default: Date.now
},
updated_at: {
type: Date,
default: Date.now
},
})
module.exports = Client = mongoose.model("client", ClientSchema);
ERROR Message: Cannot read property 'name' of undefined.
I tried all I can do, changing some code, hard coded some fields, but nothing works.
How to fix the error I get?