my objective is to push a message into the messages property (which is an array) of a user object using Mongoose. However, I get an error when I try to save the user (user.save()). I did these three console.logs on the code below to see what went wrong. Can someone fix this?
console.log(user.messages);
user.messages.push(result._id);
console.log(user.messages)
user.save(function (err, result) {
console.log(err)
});
So, one before I push the message into the array, one right after and one to check the error after I tried to save the user. This gave me the following logs:
first, an empty array
[]
second, an array containing the message ID
["5a5cdd894504771c80c8901a"]
Third, the error why it didn't save the user properly:
{ MongoError: Unknown modifier: $pushAll
at Function.MongoError.create (C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb-core\lib\error.js:31:11)
at toError (C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb\lib\utils.js:139:22)
at C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb\lib\collection.js:1059:67
at C:\Users\TijlD\Desktop\projects\03 MongoDB\node_modules\mongodb-core\lib\connection\pool.js:469:18
at process._tickCallback (internal/process/next_tick.js:150:11)
name: 'MongoError',
message: 'Unknown modifier: $pushAll',
driver: true,
index: 0,
code: 9,
errmsg: 'Unknown modifier: $pushAll' }
This is the code on the server side (node.js)
router.post('/', function (req,res,next){
// We stored the user in the token so we can retrieve it from this token.
// fetch the user (in the token) who reached this route
// we use the jwt package to decode the token ( we wont be able to grab the user if we skip this step)
// the decode method does not check if the token is valid, this happens
// higher up in this file. we only decode it to grab the user. If we hadn't
// protected our route we wouldve had to use a different strategy (.verify method)
var decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, function(err, user){
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
var message = new Message({
content: req.body.content,
user: user._id
});
message.save(function(err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
console.log(user.messages);
user.messages.push(result._id);
console.log(user.messages)
user.save(function (err, result) {
console.log(err)
});
res.status(201).json({
message: 'Saved message',
// this object is what we'll receive in the front-end
// and what we'll convert using the response.json() method
obj: result
});
});
});
});
This is the user Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true},
messages: [{type: Schema.Types.ObjectId, ref: 'Message'}]
});
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('User', schema);
according to this issue, $pushAll has beed deprecated, you can get around this by setting { usePushEach: true } in you schema options
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true},
messages: [{type: Schema.Types.ObjectId, ref: 'Message'}]
}, { usePushEach: true });
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('User', schema);
Related
This question already has answers here:
How to avoid 'cannot read property of undefined' errors?
(18 answers)
Closed 1 year ago.
I'm trying to access Dashboard but I'm getting an error.
TypeError: Cannot read property 'id' of undefined
I have created a route to access DASHBOARD using Express Router. ('routes/index')
const express = require('express')
const router = express.Router()
const User = require('../models/User')
router.get("/dashboard", async (req, res) => {
try {
const users = await User.find({ user: req.user.id }).lean() //This line is generating the error
res.render("dashboard", {
name: req.user.name,
users
});
} catch (err) {
console.log(err);
res.render('error/500')
}
})
module.exports = router
I have added this route in my app.js file
app.use('/',require('./routes/index'))
This is my MongoDB Database Schema ('models/User')
const mongoose =require("mongoose");
const UserSchema = new mongoose.Schema({
name: {
type: String,
required:true
},
email: {
type: String,
required:true,
unique:true
},
password: {
type: String,
required:true
},
confirmpassword: {
type: String,
required:true
},
tokens: [{
token: {
type: String,
required: true
}
}],
role: {
type: String,
required:true
},
createdAt: {
type: Date,
default: Date.now
}
})
module.exports = mongoose.model('User', UserSchema);
I have successfully registered and saved a user in my database
[Database Entry][1]
So error is because, your id is not define.
Please console.log(req.user) or console.log(req.body), you will know what you are getting.
Request doesn't include user object. You should get empty array when console.log(req.body).
You can do like this:
req.user = await User.findById(yourdata.id)
Then you can use req.user.id
I am trying to read data from the mongo database , but I am getting error.
I will explain what I did.
create two schema
let CompanySchema = new Schema({
name: {type: String, required: true, max: 100},
contactPerson: {type: String},
});
// Export the model
module.exports = mongoose.model('Company', CompanySchema);
let UserSchema = new Schema({
name: {type: String, required: true, max: 100},
companyId:{ type: Schema.Types.ObjectId, ref: 'companyId' }
});
// Export the model
module.exports = mongoose.model('UserTest', UserSchema);
First, add one company like this.which is successfully added
app.get('/addCompany', async (req, res) => {
let company = new Company({
name: 'Test 1',
contactPerson: 'rajesh'
})
company.save(function (err) {
if (err) {
console.log(err);
res.status(500).send(err);
// return next(err);
}
res.send('company added successfully')
//res.render('index', { title: 'Express'})
});
})
Then I added a user like this .which is successfully added.
app.get('/addUser', async (req, res) => {
let user = new User({
name: 'Test 1',
companyId: '5d3d46b2825d7f0eaf9d9d27'
})
user.save(function (err) {
if (err) {
console.log(err);
res.status(500).send(err);
// return next(err);
}
res.send('user added successfully')
//res.render('index', { title: 'Express'})
});
})
Now I am trying to fetch all user with company detail and getting error
app.get('/getUser', async (req, res) => {
User
.find({})
.populate('companyId') // only works if we pushed refs to person.eventsAttended
.exec(function(err, data) {
if (err) {
console.log(err)
return;
}
res.send(data);
});
})
error
MissingSchemaError: Schema hasn't been registered for model "companyId".
Use mongoose.model(name, schema)
at new MissingSchemaError (/Users/b0207296/WebstormProjects/untitled2/node_modules/mongoose/lib/error/missingSchema.js:22:11)
at NativeConnection.Connection.mode
Can you try now after changing your second schema to this :
let UserSchema = new Schema({
name: {type: String, required: true, max: 100},
companyId:{ type: Schema.Types.ObjectId, ref: 'Company' }
});
module.exports = mongoose.model('UserTest', UserSchema);
Assuming companyId's has matching documents in _id's of Company. Similar kind of functionality can also be achieved thru $lookup of mongoDB.
in ref you should pass the Company instead of company id
let UserSchema = new Schema({
name: {type: String, required: true, max: 100},
companyId:{ type: Schema.Types.ObjectId, ref: 'Company' }
});
My Model Schema
const UserSchema = mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
},
tweets: []
});
This are the methods i use to communicate with mongo
module.exports.getUserByUsername = function(username, callback){
const query = {username: username}
User.findOne(query, callback);
}
module.exports.addTweet = function(newTweet, newUser, callback){
User.updateOne(newUser, {$push: newTweet}, (err, isUpdate) => {
if(err) throw err;
callback(null, isUpdate)
});
}
Im using NodeJS to code my backend, i already register a user and a login but when i try to post a tweet with that user i get an error realted with the _id and i never use the ids.
router.post('/post', passport.authenticate('jwt', {session:false}), (req, res, next) => {
let newTweet = new User({
tweets:{
title: req.body.title,
body: req.body.body
}
})
User.getUserByUsername(req.body.username, (err, usert) => {
if(err) throw err;
if(!usert){
return res.json({success: false, msg: 'User not found'});
}
User.addTweet(newTweet, usert, (err, isUpdate) =>{
if(err) throw err;
if(isUpdate){
return res.json({success: true, msg: "Tweet Post"});
}
});
});
});
The Error
This is the error i get using PostMan
/home/daniel/react/miapp/Back/node_modules/mongodb/lib/utils.js:132
throw err;
^
MongoError: The field '_id' must be an array but is of type objectId in document {_id: ObjectId('5b26b4e911c67c4cfa6917e4')}
at Function.MongoError.create (/home/daniel/react/miapp/Back/node_modules/mongodb-core/lib/error.js:45:10)
at toError (/home/daniel/react/miapp/Back/node_modules/mongodb/lib/utils.js:149:22)
at /home/daniel/react/miapp/Back/node_modules/mongodb/lib/collection.js:1035:39
at /home/daniel/react/miapp/Back/node_modules/mongodb-core/lib/connection/pool.js:541:18
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Your getUserByUsername() returns a document fromthe mongo collection like
{_id: Object("...."), .....}
If you just want the username add a project query to your getUserByUsername() as:
const project = {_id:0,username:1}
User.findOne(query, project,callback)
This returns only the username of the document.
Also change the definition of new tweet to:
let newTweet = {tweets: {title: req.body.title,body: req.body.body}}
Edit: What you can also do is let your getUserByUsername code as before instead change your updateOne code(define newTweet as mentioned above):
User.updateOne({_id: newUser._id}, newTweet, callback)
Ideally, you should project only the _id from the mongo collection and query it while updating as it not only saves you from the network throughout of retreiving unnecessary data but the update query is also fast due to indexing.
When I submit my content it shows ERR_EMPTY_RESPONSE. In my node console, it shows me the Error: RangeError: Maximum call stack size exceeded. When I restart my server message content field will show. In my database, the message model has content value but users model has no message id.
I am using Mongoose 5.0.0.
when check my db it shows messages=[]
db.users.find()
{ "_id" : ObjectId("5a771f08ee207b13808a2599"), "firstName" : "rakib", "lastName" : "vai", "password" : "$2a$10$kCGCyFOPCedZcs.4Y6D.Huq02aYycuEssj5suTh00bRJSCGw1N3VO", "email" : "xxxxxx#gmail.com", "messages" : [ ], "__v" : 0 }
In my messages collection show like this
db.messages.find()
{ "_id" : ObjectId("5a771f20ee207b13808a259a"), "content" : "rakibvai", "user" : ObjectId("5a771f08ee207b13808a2599"), "__v" : 0 }
My message model file:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user');
var schema = new Schema({
content: {type: String, required: true},
user: {type: Schema.Types.ObjectId, ref: 'User'}
});
schema.post('remove', function (message) {
User.findById(message.user, function (err, user) {
user.messages.pull(message);
user.save();
});
});
module.exports = mongoose.model('Message', schema);
And my user model file:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true},
messages: [{type: Schema.Types.ObjectId, ref: 'Message'}]
});
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('User', schema);
my message.js route
router.post('/', function (req, res, next) {
var decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, function (err, user) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
var message = new Message({
content: req.body.content,
user: user
});
message.save(function (err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
user.messages.push(result);
user.save();
res.status(201).json({
message: 'Saved message',
obj: result
});
});
});
});
Not 100% certain if what I want to achieve is the correct way of doing it, so please correct me if I'm wrong.
I'm building a nodejs, express & passport website/app.
In my routes.js, I have the following section:
/* GET Home Page */
router.get('/dashboard', isAuthenticated, function(req, res){
res.render('dashboard', {
user: req.user,
sess: req.session
});
});
After the user is logged in, it displays the 'dashboard'. On that 'dashboard' I'd like to include 10 of their recent logbook entries. I have logbook.js model set up, I'm just unsure how to call it.
My function within models/logbook.js is:
function getLatestEntries(req, res, user){
Logbook.find({ 'uid' : user.uid }, {}, { limit: 10}, function(err, logbook){
return logbook;
});
}
Contents of logbook.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var logbookSchema = new Schema({
id: String,
uid: String,
lid: { type: String, unique: true},
callsign: String,
contact: String,
start: String,
end: String,
band: String,
mode: String,
RSTsent: String,
RSTrec: String,
notes: String
});
var Logbook = mongoose.model('Logbook', logbookSchema);
function getLatestEntries(req, next){
Logbook.find({ 'uid' : sess.uid }, {}, { limit: 10}, function(err, logbook){
if (err){
console.log("Error"+err)
return next(err, null);
}
return next(null, logbook);
});
}
module.exports.getLatestEntries = getLatestEntries;
// make this available to our users in our Node applications
module.exports = Logbook;
In your routes.js:
var Logbook = require('./models/logbook'); // change path if it's wrong
/* GET Home Page */
router.get('/dashboard', isAuthenticated, function(req, res, next) {
Logbook.find({ 'uid' : req.user.uid }, {}, { limit: 10}, function(err, logbook){
if (err) { console.log(err); return next(); }
res.render('dashboard', {
user: req.user,
logbook: logbook
});
});
});
In your models/logbook.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var logbookSchema = new Schema({
id: String,
uid: String,
lid: { type: String, unique: true},
callsign: String,
contact: String,
start: String,
end: String,
band: String,
mode: String,
RSTsent: String,
RSTrec: String,
notes: String
});
var Logbook = mongoose.model('Logbook', logbookSchema);
// make this available to our users in our Node applications
module.exports = Logbook;