Upsert Mongoose Error - node.js

I'm pretty new to Mongoose/Mongo and node.js, so I suspect this is just a misunderstanding on my side, I have some problem when I try to upsert my object.
Here What have I try to use upsert in my code :
app.post("/api/orders/:id", async (req, res) => {
const { id, name, email, phone, data, item } = req.body;
const existingVisitor = await Visitor.findOne({ email: email.trim() });
if(existingVisitor){
delete Visitor._id;
}
const OrderSchema = await new Order({
orderDate: new Date(),
item: item
});
const visitor = await new Visitor(
{ email: email.trim() },
{
name: name,
email: email.trim(),
phone: phone,
data: data,
createDate: new Date(),
_user: req.params.id,
order: [OrderSchema]
},
{ upsert: true, setDefaultsOnInsert: true }
);
try {
await visitor.update();
console.log("Sucess!");
} catch (err) {
res.status(422).send(err);
}
When I'm Trying to test it in Postman, I got error result following error : After applying the update to the document {_id: ObjectId('59f1896ccabc4f12bc17e5c6') , ...}, the (immutable) field '_id' was found to have been altered to _id: null
What should I do to fix that error?

Related

Mongoose user.save() doesn't return updated _id

I have a simple code that uses mongoose with nodejs to save a user object but when I log the result object that is return from save() method it is just the object I sent and the _id and id values are undefined.
Still, the object is saved correctly in the database with the new _id.
this is my code
`
import { mongoose } from "mongoose";
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
required: true,
},
age: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
},
});
export const addUser = async (_user) => {
let user = new User({ ..._user });
let result;
try {
result = await user.save();
console.log(result._id);
} catch (err) {
console.log(err);
}
return result;
};
`
I expect console.log(result._id) to have the new generated Id but it is undefined even though it is saved correctly to the database
The solution that worked for me is to assign the _id before calling save()
export const addUser = async (_user) => {
let user = new User({ ..._user });
user._id = mongoose.Types.ObjectId();
let result;
try {
result = await user.save();
console.log(result._id);
} catch (err) {
console.log(err);
}
return result;
};

Mongoose get multiple collection data using query

I am trying to join two mongoose collection and fetch all related details using the query which i have mention below. Problem is I am getting only one table details employee collection not able get two collection detail when I call GetEmployeeDetails(emp_id) . Need a suggestion. How to get two collection data in one query.
const EmployeeInfoSchema = mongoose.Schema({
employee_id: String,
client_id: {
type: Schema.Types.Number,
ref: "client",
},
email: String,
contact: String,
});
const ClientInfoSchema = mongoose.Schema({
client_id: Number,
employee_id: {
type: Schema.Types.String,
ref: "employee",
},
project: String,
organization: String,
});
let employeeInfo = mongoose.model("employee", EmployeeInfoSchema);
let clientInfo = mongoose.model("client", ClientInfoSchema);
module.exports = { employeeInfo, clientInfo };
Query
async function GetEmployeeDetails(emp_id) {
let employee_info = await Storage.employeeInfo
.find()
.where({ employee_id: emp_id })
.populate({
path: "client",
})
.exec(function (err, block) {
if (err) {
console.log("%s", err);
}
console.log("Employee details is %s", employee_info);
});
return employee_info;
}
Try to change your GetEmployeeDetails method like this:
async function GetEmployeeDetails(emp_id) {
try {
let employee_info = await Storage.employeeInfo
.find({ employee_id: emp_id })
.populate('client')
.exec(function (err, block) {
if (err) console.log('%s', err);
else console.log('Employee details is %s', employee_info);
});
return employee_info;
} catch (err) {
res.status(400).send('Error getting details');
}
}

Pass a Button value and Update the database

Working on a personal project, one of the functions of the project is to update the user status on what event they are participating.
i wanted to submit a value using a button
<form action="/users/fooddrivebanner" method="POST"><button name="fooddrive" type="submit" value="fooddrive" id="fooddrive">Participate</button></form>
then pass the value to my route and save it inside my database
router.post('/fooddrivebanner', (req,res)=>{
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
User.findOne({ _id: _id }).then((user)=>{
if (!user) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
if (typeof eventparticpating !== "undefined") {
user.eventparticpating = 'fooddrive';
}
user.save(function (err, resolve) {
if(err)
console.log('db error', err)
// saved!
});
})
.catch((err) => console.log(err));
Here is the User model
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
eventparticpating: {
type: String,
default: 'None At The Moment'
}
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
It showed a console error
TypeError: Cannot set property 'eventparticpating' of null
UPDATE
Edit 1:
I followed Mr Gambino instructions, error Gone yet cannot update the database, how would i be able to adjust and find my user?
Instead of saving within the findOne function,you can do this:
router.post('/fooddrivebanner', async (req,res) => {
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
await User.findOne({ _id: _id }, (error, user) => {
if (error) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
}).updateOne({ eventparticpating: "foodrive" });
});
I hope that answers your question

Express api with mongoose PUT

I have endpoint:
router.put('/:customerId', async (req, res) => {
try {
const updatedCustomer = await Customer.updateOne(
{ _id: req.params.customerId },
req.body,
{ new: true }
);
res.send(updatedCustomer);
} catch {
res.json({ message: err });
}
});
const CustomerSchema = mongoose.Schema({
name: String,
surname: String
})
and after put request with only name value in my object still exist name and surname. I thought that my surname value will be delete. It works fine or not?
In your schema definition do the following
const CustomerSchema = mongoose.Schema({
name: String,
surname: String
},{
strict:false
})

mongoose.updateOne() always updating the first document

I'm making a command for a discord bot in which I want to edit user's info in document. The command looks like this !edit #tag email language this works however it doesnt matter who I ping it will always change the first document in MongoDB.
let user = message.mentions.users.first()
Data.findOne({
userID: user.id,
}, (err, data) => {
if (err) return console.log(err);
if (!data) {
return message.reply("That user isn't in list")
} else {
Data.updateOne({
language: args[2],
email: args[1]
}, (err) => {
if (err) throw err;
let embed = new Discord.MessageEmbed()
.addField("Name", data.name);
message.channel.send(embed)
})
}
Data.js
const mongoose = require("mongoose");
const dataSchema = mongoose.Schema({
name: String,
language: String,
email: String,
userID: String,
lb: String,
usage: Number
})
module.exports = mongoose.model(`Data`, dataSchema)
This is how my documents look like
May you should try this
Data.findOneAndUpdate({ userID: user.id },
{ $set: { language: args[2], email: args[1] } },
{ new: true }).exec((err, data) => {
//further response with updated data
});

Resources