Cannot read property 'username' of undefined in mongoose - node.js

I want to access user object inside of the for loop but I get the error.
User.find({resume :{$ne : null}}, (err,user)=>{
if(err) res.send('ther is some problem for updating resumes') ;
if(user){
for(var i = 0 ; i < user.length ; i++){
Like.count({for : user[i].username }, (err,count)=>{
if(err) res.send('there is something wrong with counting likes');
console.log('inside: ' + user[i].username);
})
}
}
})
user.js
var mongoose = require('mongoose') ;
var schema = mongoose.Schema({
username : {
type : String,
require : true
},
password : {
type : String,
require : true ,
},
resume : {
type : String
},
date : {
type : Date,
default : Date.now()
}
})
module.exports= mongoose.model("user",schema) ;
I can't firgure out what is wrong !

Try this:
User.find({ resume: { $ne: null } }, (err, users) => {
if (err) res.send('there is some problem for updating resumes');
//for debugging, temporarily log number of users found...
console.log(`${users.length} were found with no resume!`);
if (users.length > 0) {
users.forEach((user) => {
Like.count({ for: user.username }, (err, count) => {
if (err) res.send('there is something wrong with counting likes');
console.log('inside: ' + user.username);
})
});
}
});
Pointers
users is an array, you cannot check for falsy on array with if (array), because empty arrays are truthy. So check the length if (array.length > 0.
this wasn't your problem, but it's safer to use native array methods than your own for loops., e.g. users.forEach... instead of for (var i = 0; ....

Related

Remove object array items by comparing object array from mongodb

There is document which is having array of object inside.
Like
Objectid('')
fruits : [{_id:'2'},{_id:'3'},{_id:'4'}]
I want to delete these items fruits_id = [{_id:'3'},{_id:'4'}].
fruit_group.updateOne(
{collection_id: collection_id},
{$pullAll: {"fruits": fruits_id}}
)
so far i found below logic which i think is not efficient.
routes.post('/removeFruits', async (request, response, next) => {
var post_data = request.body;
var collection_id = post_data.collection_id;
var fruits_ids = JSON.parse(post_data.fruits_ids);
var prev_fruits;
await fruit_group.findOne({'collection_id': collection_id}, function (err, result) {
if (err) {
console("Some error occurred");
response.json({'message': "Some error occurred", 'result': 'false'});
}
prev_fruits = result.fruits;
});
for (var i = 0; i < fruits_ids.length; i++) { // this will delete all occurring items from array
var key = fruits_ids[i].user_id;
prev_fruits.filter(x => x.user_id === key).forEach(x => prev_fruits.splice(prev_fruits.indexOf(x), 1));
}
await fruit_group.updateOne({'collection_id': collection_id}, {$set: {'fruits': prev_fruits}}, function (err, result) {
if (err) {
response.json({'message': "Some error occurred", 'result': 'false'});
}
response.json({'message': 'Deletion successfully', 'result': 'true'});
});
});
is there anyway to achieve the same result?
Assuming fruits_id = [{ _id: '3' }, { _id: '4' }], you could do something like this using $pull and $in:
await fruit_group.updateOne({'collection_id': collection_id}, { $pull: { fruits: { $in: fruits_id }}})
This follows the example of removing all items that equal a specified value.

mongdb monk -Argument passed in must be a single String of 12 bytes or a string of 24 hex characters

I am having the error : Argument passed in must be a single String of 12 bytes or a string of 24 hex characters. When I tried to use find query using IDs obtained in a previous query. I tried casting them as ObjectIds but it gives me the same error. Your kind help is greatly appreciated. The following is my code:
var bookIds = []
for(var j = 0; j < cart.length; j++){
bookIds.push(cart[j].bookId);
}
bookCollection.find({_id:{$in:bookIds}}, {}, function(err, books){
if(err !== null){
console.log(err);
res.send({"msg":"Add to cart error"});
}
if(books){
console.log("new cart");
console.log(cart);
console.log(books);
res.json(books);
}
else{
res.send({"msg":"Add to cart error"});
}
});
content of cart:
[ { bookId: '5ac5cdf3532808df2e80281e', quantity: 3 },
{ bookId: '5ac5d30479705c2a30a0c235', quantity: 4 },
{ bookId: '5ac5cdfd532808df2e80281f', quantity: 1 },
{ bookId: '5ac5cfe379705c2a30a0c23', quantity: '2' } ]
You don't need to cast them they are already ObjectId when you store them as ObjectId or ref of other model.
const bookIds = cart.map({bookId} => bookId);
bookCollection.find({ "_id" :{ "$in": bookIds }})
.then(books => {
console.log("new cart");
console.log(cart);
console.log(books);
res.json(books);
})
.catch(err => {
console.log(err);
res.send({"msg":"Add to cart error"});
})
This is because _id must be type Mongoose.Types.ObjectId
To Resolve :
objectId = require('mongoose').Types.ObjectId;
for(var j = 0; j < cart.length; j++){
bookIds.push(new objectId(cart[j].bookId));
}

Mongoose save not working for some odd reason from a findOne

Gig.findOne({
_id: data.gig
}).populate(populate).exec(function(err, gig) {
gig.lastChatTime = Date.now();
gig.lastChatBy = params.by;
gig.meta.chats += 1;
return gig.save(function(err) {
return console.log(err);
});
});
When I do the .save, it doesn't save, but it also doesn't error. What gives?
try something like this
Gig.findOne({
_id: data.gig
}).populate(populate).exec(function(err, gig) {
if(gig){
Gig.update({_id: gig._id},
{
lastChatTime : Date.now(),
lastChatBy : params.by,
meta.chats : meta.chats+ 1
},
{
runValidators: true
},function(err){
if(err){
throw err;
}
);
}
});

node.js + mongoose + HTTP PUT Not Working

I'm following scotch's tutorial, so I have this user schema:
var userSchema = mongoose.Schema({
local : {
email : String,
password : String,
},
facebook : {
id : String,
token : String,
email : String,
name : String
},
twitter : {
id : String,
token : String,
displayName : String,
username : String
},
google : {
id : String,
token : String,
email : String,
name : String
}
});
I'm trying to make a http put to update some data with x-www-form-urlencoded, but I'm not able to set the fields, this is what I have:
PUT /teacherup HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
email=example%40gmail.com&password=randompass
How can I make an appropriate http put and set those fields? I would also like to know how to do this with JSON.
-- Update with put
Here's the http put:
app.put('/teacherup', isLoggedIn, function(req, res) {
if(req.user.usertype == 1)
{
util.updateDocument(req.user, userschema, req.body);
req.user.save(function(err) {
if (err)
throw err;
});
res.send(200, {message : 'Teacher saved!'});
}
else
{
res.send(406, {message : 'Not a teacher!'});
}
});
-- Update methods for saving doc
I'm using these methods for updating a doc
exports.updateDocument = function(doc, SchemaTarget, data) {
for (var field in SchemaTarget.schema.paths) {
if ((field !== '_id') && (field !== '__v')) {
var newValue = getObjValue(field, data);
console.log('data[' + field + '] = ' + newValue);
if (newValue !== undefined) {
setObjValue(field, doc, newValue);
}
}
}
return doc;
};
function getObjValue(field, data) {
return _.reduce(field.split("."), function(obj, f) {
if(obj) return obj[f];
}, data);
}
function setObjValue(field, data, value) {
var fieldArr = field.split('.');
return _.reduce(fieldArr, function(o, f, i) {
if(i == fieldArr.length-1) {
o[f] = value;
} else {
if(!o[f]) o[f] = {};
}
return o[f];
}, data);
}
I am showing you the server side code for inserting a new document using 'express' and 'mongoose'. Hope this will helps you.
var app = require('express)(),
mongoose=require('mongoose'),
userModel=mongoose.model("user", userSchema);
app.put('/teacherup', update);
update=function(req,res){
new userModel
.save(object)//I have not created the object you have to create it according to yourschema
.exec(function(err, result) {
if (err) {
console.log(err);
} else {
console.log("Successfully inserted");
}
});
}

Mongoose model get undefined properties after population

I got a problem for a basic request.
All properties of a mongoose model I fetch are undefined in the exec() callback.
Here is my schema :
userSchema: new Schema({
email: { type: String, limit: 50, index: true },
password: String,
birthdate: { type: Date },
active: { type: Boolean, default: true },
friends: [{
_friend: { type: Schema.ObjectId, ref: 'User' },
addedDate: { type: Date, default: Date.now }
}],
registrationDate: { type: Date, default: Date.now }
})
You can already notice that my "friends" property is an array of objects referencing another schema.
Now here is my query :
dbModels.User
.find({ _id: req.session.user._id })
.populate('friends._friend', 'email birthdate')
.exec(function (err, _user){
if (err || !_user){
apiUtils.errorResponse(res, sw, 'Error when fetching friends.', 500);
} else {
console.log('user', _user);
// This output the object with all its properties
console.log('user birthdate', _user.birthdate);
// _user.birthdate is undefined
console.log('user friends', _user.friends);
// _user.friends is undefined
apiUtils.jsonResponse(res, sw, _user);
}
});
When this web service return '_user', each properties are well defined and have the correct values.
The problem is that I only want to return _user.friends which is not possible since it's undefined.
Now, here is apiUtils.jsonResponse function :
exports.jsonResponse = function (res, sw, body) {
console.log(body.friends);
// At this breakpoint, body.friends is still undefined
(sw || _sw).setHeaders(res);
if (util.isArray(body)) {
for (var i = 0; i < body.length; i++) {
body[i] = exports.cleanResults(body[i]);
}
} else {
console.log(body.friends);
// At this breakpoint body.friends is still undefined
body = exports.cleanResults(body);
}
res.send(httpCode || 200, JSON.stringify(body));
};
And the cleanResults function :
exports.cleanResults = function (body) {
console.log(body.friends);
// At this point, body.friends is FINALLY DEFINED
if (typeof body.toObject === 'function') {
body = body.toObject();
delete body.__v;
}
for (var attr in body) {
if (body.hasOwnProperty(attr) && attr[0] == '_') {
var _attr = attr.replace('_', '');
body[_attr] = body[attr];
delete body[attr];
}
}
return body;
};
I tried to set a timeout to see if the problem came from async but it changed nothing. I'm a bit desesperate at this time and I wanted to know if you already encountered the same problem before ?
I see your problem, you have accidentally used find when you expect only one object to be returned. In this case, you should use findById:
User
.findById(req.session.user._id)
.populate('friends._friend', 'name surname picture birthdate')
.exec(function(err, user) {
...
})

Resources