Express, Mongoose - .update() is returning null - javascript

When I am trying to update a document in my model, the .update() is returning null but the .find() method works fine.
module.exports.updateBio = function(req, res) {
var userID = req.params.id;
var objForUpdate = {};
if (!troolr.isEmptyString(req.body.profile_picture)) objForUpdate.profile_picture = req.body.profile_picture;
if (!troolr.isEmptyString(req.body.title)) objForUpdate.title = req.body.title;
if (!troolr.isEmptyString(req.body.intro)) objForUpdate.intro = req.body.intro;
if (!troolr.isEmptyString(req.body.summary)) objForUpdate.summary = req.body.summary;
if (!troolr.isEmptyString(req.body.skills)) objForUpdate.skills = req.body.skills;
if (!troolr.isEmptyString(req.body.facebook)) objForUpdate.social.facebook = req.body.facebook;
if (!troolr.isEmptyString(req.body.twitter)) objForUpdate.social.twitter = req.body.twitter;
if (!troolr.isEmptyString(req.body.linkedin)) objForUpdate.social.linkedin = req.body.linkedin;
if (!troolr.isEmptyString(req.body.website)) objForUpdate.social.website = req.body.website;
var conditions = { "_id": userID }
, setObj = { $set: objForUpdate }
, options = { multi: true };
//This throws error
// Error: { ok: 0, n: 0, nModified: 0 }
Profile.update(conditions, setObj, (err, page) =>{
if(err) throw err;
console.log(page);
});
// This works fine but it erases old values if they are empty
/* Profile.findById(userID, (error, user) => {
if(error) return res.status(500).json({ success: false, error: error });
user.bio = objForUpdate;
user.save(function(error) {
if(error) return res.status(500).json({ success: false, error: error });
return res.status(200).json({ success: true, message: "Bio successfully updated." });
});
}); */
};
// API Endpoint
http://localhost:3000/api/v1/profile/592c53b3bdf350ce004ad717/updatebio
// API Define
'use strict';
/**
* Routes for Profile Model
*
**/
var passport = require('passport');
var jwt = require('jwt-simple');
var settings = require("settings");
var profileCtrl = require(settings.PROJECT_DIR + 'routes/controllers/api/profile');
module.exports = function(app) {
app.get('/all', profileCtrl.getAll);
app.get('/:id', profileCtrl.getSingle);
app.put('/:id/updateurl', profileCtrl.updateURL);
app.put('/:id/updateaddress', profileCtrl.updateAddress);
app.put('/:id/updatebio', profileCtrl.updateBio);
}
// Model
var mongoose = require('mongoose');
// User Schema
var ProfileSchema = mongoose.Schema({
url : {
type: String,
unique: true,
},
fname: {
type: String,
required: true
},
lname: {
type: String,
required: true
},
email: {
type: String,
unique: true,
required: true
},
bio: {
profile_picture: {
type: String
},
title: {
type: String
},
intro: {
type: String
},
summary: {
type: String
},
skills: {
type: Object
},
social: {
linkedin: {
type: String
},
twitter: {
type: String
},
facebook: {
type: String
},
website: {
type: String
}
},
},
location: {
address: {
type: String
},
apt: {
type: String
},
city: {
type: String
},
state: {
type: String
},
zip_code: {
type: String
},
country: {
type: String
}
},
phone: {
type: Number
},
listings: {
type: Object
},
reviews: {
type: Object
},
verfied: {
type: Boolean,
default: false
},
// expires: {
// type: Date,
// expires: '1h',
// default: Date.now
// },
});
var Profile = module.exports = mongoose.model('Profile', ProfileSchema);
module.exports.getUserByEmail = function(email, callback){
var query = {'email': email};
Profile.findOne(query, callback);
}
module.exports.checkIfUrlExists = function(res, url, callback){
var query = {'url': url};
Profile.findOne(query, function(error, found) {
if(error) return res.status(500).json(error);
if(found) return res.status(500).json({success: false, message: "URL already exists" });
if(callback) callback();
});
}
// Document which I am trying to update
{
"_id": "592c53b3bdf350ce004ad717",
"url": "hyoh7ryb-",
"fname": "Foo",
"lname": "Bar",
"email": "foobar#gmail.com",
"__v": 0,
"verfied": false
}

Anything not defined in schema is not saved. That's what happening when you're missing bio key while preparing the objForUpdate to $set:
var objForUpdate = {};
if (!troolr.isEmptyString(req.body.profile_picture)) objForUpdate.profile_picture = req.body.profile_picture;
which should be
var objForUpdate = {
bio: {}
};
if (!troolr.isEmptyString(req.body.profile_picture)) objForUpdate.bio.profile_picture = req.body.profile_picture;
if (!troolr.isEmptyString(req.body.title)) objForUpdate.bio.title = req.body.title;
// and so on
Your save is working because of saving the object in the right keyuser.bio = objForUpdate;

Related

Unable to get the values from one schema to another schema

I create a order schema which have two models; StudentConsessionSchema and consessionSchema
StudentConsessionSchema acquire the student model (student model contain the details about the student).
The other model consessionSchema acquire the StudentConsessionSchema (for acquiring the student details).
When I test it in postman to order it works but it's not able to get the student details in consessionSchema.
order schema:
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const StudentConsessionSchema = new mongoose.Schema({
student: {
type: ObjectId,
ref: "Student", //ref to the student model from another file
},
FullName: {
type: String,
},
addmissionNumber: {
type: String,
required: true,
trim: true,
maxlength: 8,
},
faculty: {
type: ObjectId, //ref to the faculty model from another file
ref: "Faculty",
required: true,
},
});
const StudentConsession = mongoose.model(
"StudentConsession",
StudentConsessionSchema
);
const consessionSchema = new mongoose.Schema(
{
student: [StudentConsessionSchema], //this returns [] empty array
consession_id: {},
fromStation: {
type: String,
required: true,
},
toStation: {
type: String,
default: "Dadar",
},
passType: {
type: String,
enum: ["I", "II"],
required: true,
},
ticketPeriod: {
type: String,
enum: ["Monthly", "Quarterly"],
default: "Monthly",
required: true,
},
status: {
type: String,
default: "Pending",
enum: ["Pending", "Cancelled", "Accepted", "Printed"],
},
updated: Date,
},
{ timestamps: true }
);
const Consession = mongoose.model("Consession", consessionSchema);
module.exports = { StudentConsession, Consession };
create order controller:
exports.createOrder = (req, res) => {
let form = new formidable.IncomingForm();
form.keepExtensions = true;
form.parse(req, (err, fields) => {
const {
admissionNumber,
fullName,
faculty,
fromStation,
toStation,
passType,
ticketPeriod,
} = fields;
if (
!admissionNumber ||
!fullName ||
!faculty ||
!fromStation ||
!toStation ||
!passType ||
!ticketPeriod
) {
return res.status(400).json({
error: "Please fill all fields",
});
}
let consession = new Consession(fields);
// const consession = new Consession(req.body.consession);
if (req.student.pass === 1) {
return res.status(400).json({
error:
"You are not eligible to make request Because You already have a pass",
});
}
consession.save((err, order) => {
if (err) {
console.log(err);
return res.status(400).json({
error: "Failed to make order",
});
}
res.json(order);
});
});
};
output:
{
"toStation": "abc",
"ticketPeriod": "Monthly",
"status": "Pending",
"_id": "600e789887b9a201bc4c2d1a",
"fromStation": "xyz",
"passType": "II",
"student": [],
"createdAt": "2021-01-25T07:51:52.091Z",
"updatedAt": "2021-01-25T07:51:52.091Z",
"__v": 0
}
My questions is why is the student array empty?

Request failed with status code 404 when passing items to MongoDB

First of all, I'm a real beginner to programming and I can't figure out what is wrong with this
it only shows an error of 404 not found
Below is my mongoose schema
const mongoose = require("mongoose");
const OrderSchema = new mongoose.Schema({
user_id: {
type: String,
required: true,
},
order_date: {
type: Date,
default: Date.now,
},
total_items: {
type: Number,
required: true,
},
total: {
type: Number,
required: true,
},
name: {
type: String,
},
address: {
type: String,
},
postalcode: {
type: String,
},
city: {
type: String,
},
country: {
type: String,
},
phonenumber: {
type: Number,
},
order_item_status: {
//purchased item delivery status, added by constant at saving from controller nmethod
type: String,
required: true,
},
quantity_array: [
{
type: String,
required: true,
},
],
purchase_array: [
{
type: String,
required: true,
},
],
item_array: [
{
type: String,
required: true,
},
],
});
module.exports = Order = mongoose.model("order", OrderSchema);
And Below is the set of data that I'm sending.
{"user_id":"5f5058acc90b575a40d9e570",
"name":"Alfonso",
"address":"Victoria",
"postalcode":"11011B",
"city":"Moscow",
"country":"Russia",
"phonenumber":null,
"total_items":2,
"total":15,
"quantity_array":[2,1],
"purchase_array":["pb_single","pb_single"],
"item_array":["5f55e91271b808206c132d7c","5f55e8e171b808206c132d7a"]}
and below is the function that I use to send the above Object to the server.
let orderComplete = {
user_id: localStorage.getItem("id"),
name: this.state.name,
address: this.state.address,
postalcode: this.state.postalcode,
city: this.state.city,
country: this.state.country,
phonenumber: this.state.phonenumber,
total_items: this.state.totalitems,
total: this.state.amount,
quantity_array: this.state.quantityArray,
purchase_array: this.state.purchaseTypeArray,
item_array: this.state.comicIdArray,
};
console.log("checkpoint : orderComplete" + JSON.stringify(orderComplete));
var jwt_token = localStorage.getItem("currentToken"); //because it is a protected route
const config = {
headers: {
"Content-Type": "application/json",
"x-auth-token": jwt_token,
},
};
const body = JSON.stringify(orderComplete);
const result = await axios
.post("http://localhost:5000/createorder", body, config)
.then((res2) => {
console.log(res2);
toast.success(res2);
})
.catch((error) => {
toast.error(error);
console.log(error);
});
if (result == true) {
this.props.history.push("/products");
toast.success("Order Success");
}
}
And when it is caught from the server-side
the function is as below
const createOrder = async (req, res) => {
try {
let user_id = req.body.user_id;
let purchase_type = req.body.purchase_type;
let item_array = req.body.item_array;
let quantity_array = req.body.quantity_array;
let purchase_array = req.body.purchase_array;
let total_items = req.body.total_items;
let total = req.body.total;
let name = req.body.name;
let address = req.body.address;
let postalcode = req.body.postalcode;
let city = req.body.city;
let country = req.body.country;
let phonenumber = req.body.phonenumber;
let order_item_status = "processing";
if (
purchase_type == false ||
user_id == false ||
item_array == false ||
quantity_array == false ||
purchase_array == false ||
total_items == false ||
total == false ||
name == false ||
address == false ||
postalcode == false ||
city == false ||
country == false ||
phonenumber == false
) {
return res.status(400).send("Not all mandatory values have been set!");
}
OrderObject = new Order({
//create object to set data
purchase_type,
user_id,
item_array,
quantity_array,
purchase_array,
total_items,
total,
name,
address,
postalcode,
city,
country,
phonenumber,
order_item_status,
});
await OrderObject.save();
res.status(200).send("Order success");
} catch (error) {
console.log("Error caught at ", error);
res.status(500).send("Server Error");
}
};
I tried over and over but I can't figure out what is wrong with it, Even the exception handlers don't include much of information.
please I desperately need your help, thank you.

How to save data in mongoDB and Schema is like bellow

Here is my schema by using mongoose npm package.
var StatusSchema = new mongoose.Schema({
empName: {
projectName: { type: String },
clientName: { type: String },
statusLastWeek: { type: String },
statusThisweek: { type: String },
planNextWeek: { type: String }
}
});
Here is my nodejs code to update the data
var Status = mongoose.model('Status', StatusSchema);
module.exports = Status;
Description: Want save data in MongoDB, data schema is like above mentioned,
save saving data is sored loke as bellow.
Inside Mongo DB :
{ "_id" : ObjectId("5d92f4aba4695e2dd90ab438"), "__v" : 0 }
{ "_id" : ObjectId("5d92f4b4a4695e2dd90ab439"), "__v" : 0 }
Expected collection in MongoDB :
Dave Smith {
projectName: BLE Mesh,
clientName: Tera,
statusLastWeek: BLE Scan,
statusThisweek: BLE List View,
planNextWeek: Mqtt config
}
Here you can see my NodeJS code :
router.post ('/update', (req,res,next)=>{
userStatus = new wkStatus(req.body)
userStatus.save()
.then(status => {
res.redirect('/success');
console.log ("Status saved in DB")
})
.catch(err => console.log(err))
// return next;
});
//You can use ODM like mongoose and define a schema with mongoose.Schema. You can just
// see mongoose module document from npm. Use .save() for save an object in DB.
// Example :
// schema as admin
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const Schema = mongoose.Schema;
const bcrypt = require('bcrypt-nodejs');
const sha256 = require('sha256')
const adminSchema = new Schema({
fullName: { type: String, required: true },
userName: { type: String },
noc: { type: String, required: true },
mobileNumber: { type: String, required: true },
email: { type: String },
chacommAddress: {
contactPerson: { type: String },
country: { type: String },
address: { type: String },
city: { type: String },
pinCode: { type: String },
state: { type: String },
stateCode: { type: String },
},
address: {
country: { type: String },
city: { type: String },
pinCode: { type: String },
state: { type: String },
stateCode: { type: String },
address: { type: String },
CIN: { type: String },
GSTIN: { type: String }
},
password: { type: String, required: true },
userType: { type: Number, required: true },
createdAt: { type: Date, required: true },
uploadFile: { type: String, required: true },
bankdetails: {
bankName: { type: String },
accountNo: { type: String },
ifscCode: { type: String },
accountType: { type: String },
accountName: { type: String },
cancelledChequeCopy: { type: String }
},
isActive: { type: Boolean },
invoiceString:{type:String},
invoiceValue:{type:Number},
accountantName :{type:String} ,
accountantDesignation : {type:String},
referredBy:{type:String}
});
adminSchema.methods.comparePassword = function (password) {
let password_hash = sha256(password);
return bcrypt.compareSync(password_hash, this.password);
}
adminSchema.pre('save', function (next) {
if (!this.isModified('password'))
return next();
let password_hash = sha256(this.password);
bcrypt.hash(password_hash, null, null, (err, hash) => {
if (err)
return next(err);
this.password = hash;
next();
});
});
//export schema
// module.exports = mongoose.model('Admin', adminSchema)
// for save:
const admin = require('admin')
var obj= new admin({
// values as per model defined
})
obj.save()
const wkStatus = new wkStatus({
_id: new mongoose.Types.ObjectId(),
projectName: req.body.projectName,
clientName: req.body.clientName,
statusThisweek: req.statusThisweek,
statusLastWeek: req.statusLastWeek,
planNextWeek: req.planNextWeek
})
Status
.save()
.then(result => {
res.status(201).json({
message: "Data Created Successfully",
})
console.log(result) // show the response
})
.catch(err => {
res.status(500).json({error:err})
})
Try this way hope it will work. If need more you can message me
The schema what you are trying to create itself is wrong.
empName: {
projectName: { type: String },
clientName: { type: String },
statusLastWeek: { type: String },
statusThisweek: { type: String },
planNextWeek: { type: String }
}
The above schema can create objects like below: "empName" cannot be dynamic.
empName: {
projectName: BLE Mesh,
clientName: Tera,
statusLastWeek: BLE Scan,
statusThisweek: BLE List View,
planNextWeek: Mqtt config
}
If you want to store like what you have shown, where empName dynamically then you should make empName as Map
See https://mongoosejs.com/docs/schematypes.html#maps

Model.function is not a function within a router

Im currently stuck at a problem within my router.
I export the function as you see in the following code.
This is my Model:
"use strict";
var mongoose = require('mongoose');
var bcrypt = require("bcryptjs");
var Schema = mongoose.Schema;
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
firstname: {
type: String,
required: true
},
lastname: {
type: String,
required: true
},
gender: {
type: String,
required: true
},
country: {
type: String,
required: true
},
confirm: {
type: Number
},
confirmcode: {
type: String
},
ip: {
type: String
},
signup: {
type: Date,
default : Date.now
},
voice: {
type: String
},
steam: {
type: String
},
steamid: {
type: String
},
steamlink: {
type: String
},
battletag: {
type: String
},
showsteam: {
type: Number
},
showbnet: {
type: Number
},
birthdate: {
type: Date,
required: true
},
language: {
type: String
}
});
var User = module.exports = mongoose.model('User',UserSchema);
module.exports.createUser = function(newUser, callback){
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.comparePw = function(canPw, hash, callback){
bcrypt.compare(canPw, hash).then((res) => {
callback(null,res);
});
}
module.exports.findUserById = function(id,callback){
User.findById(id,callback);
}
module.exports.getGamer = function(count,callback){
User.count(count,callback);
}
module.exports.findUsername = function(uname, callback){
var query = {username:uname};
User.findOne(query,callback);
}
module.exports.findEmail = function(email, callback){
var query = {email:email};
User.findOne(query,callback);
}
This is my Router:
var User = require("../../model/user");
module.exports = function(router){
router.get("/user", function(req, res){
var user = new User();
user.getGamer(function(err,response){
if(err){
throw err;
}else{
res.json(response);
}
});
});
}
the error i get is:
TypeError: user.getGamer is not a function
But i dont know why. Anyone can help me ?
You need to attach model methods to the schema, not to the model. Then the methods will be available on instances of your model. See this post for more.
UserSchema.methods.getGamer = function(newUser, callback) ...

how can i exit nodejs script after mongo db write

I have 400,000 lines to enter and I need to break it up. Unfortunately I cannot get this script to exit until it's completed everything. It invariably runs out of memory of course. I thought setting a value at .on('end',function() would be useful but I can't see that value once the .on data has completed.
'use strict';
var mongoose = require('mongoose');
var fs = require('fs');
var parse = require('csv-parse');
var Schema = mongoose.Schema;
var done;
mongoose.connect('mongodb://127.0.0.1:27017/auth');
var userSchema = new mongoose.Schema({
username: {
type: String,
unique: true
},
password: String,
email: {
type: String,
unique: true
},
isActive: String,
roles: {
account: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Account'
}
},
timeCreated: {
type: Date,
default: Date.now
},
search: [String]
});
var accountSchema = new mongoose.Schema({
user: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type: String,
default: ''
}
},
isVerified: {
type: String,
default: ''
},
verificationToken: {
type: String,
default: ''
},
name: {
first: {
type: String,
default: ''
},
middle: {
type: String,
default: ''
},
last: {
type: String,
default: ''
},
full: {
type: String,
default: ''
}
},
company: {
type: String,
default: ''
},
phone: {
type: String,
default: ''
},
zip: {
type: String,
default: ''
},
memberid: {
type: String,
default: ''
},
status: {
id: {
type: String,
ref: 'Status'
},
name: {
type: String,
default: ''
},
userCreated: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type: String,
default: ''
},
time: {
type: Date,
default: Date.now
}
}
},
userCreated: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type: String,
default: ''
},
time: {
type: Date,
default: Date.now
}
},
search: [String]
});
var User = mongoose.model('User', userSchema);
var Account = mongoose.model('Account', accountSchema);
fs.createReadStream('./ipart')
.pipe(parse({
delimiter: ','
}))
.on("data-invalid", function(data) {})
.on('data', function(csvrow) {
var u = {
isActive: 'yes',
username: csvrow[0],
email: csvrow[0],
search: [
csvrow[1] + ' ' + csvrow[2],
csvrow[0],
]
};
User.create(u, function(err, createdUser) {
if (err) {
console.log(err);
return;
}
var user = createdUser;
var displayName = csvrow[1] + ' ' + csvrow[2] || '';
var nameParts = displayName.split(' ');
var acct = {
isVerified: 'no',
'name.first': nameParts[0],
'name.last': nameParts[1] || '',
'name.full': displayName,
user: {
id: user._id,
name: user.username
},
search: [
nameParts[0],
nameParts[1] || ''
]
};
Account.create(acct, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
var fieldstoset = {
roles: {
account: account._id
}
};
User.findByIdAndUpdate(account.user.id, fieldstoset, function(err, user) {
if (err) throw err;
});
});
});
})
.on('end', function() {
console.log('complete');
});
You really need to use bulk inserts, I found this code somewhere and pasting it for you
var Potato = mongoose.model('Potato', PotatoSchema);
var potatoBag = [/* a humongous amount of potato objects */];
Potato.collection.insert(potatoBag, onInsert);
function onInsert(err, docs) {
if (err) {
// TODO: handle error
} else {
console.info('%d potatoes were successfully stored.', docs.length);
}
}
I would recommend you to break down your entire logic of importing your CSV data into these following steps:
1. Write a simple script file which imports the CSV into a temporary collection like this:
YourImportScript
#!/bin/bash
mongoimport -d YourDBName -c YourTempCollectionName --drop --type csv --file pathToYourCSVFile.csv --headerline
2. Run the scripts before creating your Users:
var exec = require('child_process').exec;
function importCSV(callback) {
exec("./pathToYourImportScript/YourImportScript", function (error, stdout, stderr) {
console.log(stdout);
if (error !== null)
console.log('exec error: ' + error);
});
callback()
}
MongoImport will import the CSV pretty quickly.
Get the documents from the temp collection and insert them into your Users Collection.
You can also use async module to control the flow of your code mode neatly:
async.series([
function (callback) {
//CSV Import function
},
function (callback) {
//User Manupulation function
}]);
And it is better to put headers into your CSV columns, as you can create a model when importing documents from the temp collections, and it would be easier to get the properties of users by column headers like username:myCSVModel.username instead of username: csvrow[0].

Categories