Mongoose findOneAndUpdate won't update my database - node.js

I am teaching myself NodeJS while working on an app. I use Mongoose and Axios.
On one section of the app I display the partners and when I click on update I get a form with the informations of the selected partner in order to update them.
The client-side sends in the infos to the server but the server won't update the entries in the database. Here is my server side
app.post("/api/partner/update", (req, res) => {
const id = req.body.id;
const fullname = req.body.fullname;
const email = req.body.email;
const phones = req.body.phones;
const shops = req.body.shops;
const company = req.body.company;
console.log("The body is ",req.body) //It returns the correct data from the client's side submited data
Partner.findOneAndUpdate(id, mongoose.set('useFindAndModify', false),
{
"fullname": fullname,
"email": email,
"phones": phones,
"shops":shops,
"company": company
},
(err, document) => {
if (err) return err;
//console.log(document);
res.send({ document });
}
);});
Here is my model :
const mongoose = require("mongoose");
const partnerSchema = mongoose.Schema(
{
fullname: {
type: String,
maxlength: 50,
required: true
},
email: {
type: String,
trim: true,
unique: 1,
required: true
},
phones: {
type: Array
},
company: {
type: String,
maxlength: 50,
required: true
},
shops: {
type: Array,
default: 0
},
is_valid: {
type: Boolean
},
validated_by: {
type: String
},
created_by: {
type: String,
maxlength: 50
},
updated_by: {
type: String
},
deleted_by: {
type: String
},
deleted_at: {
type: Date,
default: null
}
},
{
timestamps: {
createdAt: "created_at",
updatedAt: "updated_at"
}
}
);
const Partner = mongoose.model("Partner", partnerSchema)
module.exports ={Partner}
I don't understand why it is not updating the fields in the dataBase

This is a syntax for findOneAndUpdate as per the docs:
var query = { name: 'borne' };
Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
Change db query to this:
let query = {_id: id };
let dataToUpdate= {
"fullname": fullname,
"email": email,
"phones": phones,
"shops":shops,
"company": company
}
let options = {useFindAndModify: false} // useFindAndModify set to false at query level
// options = {useFindAndModify: false,new:true} if you want updated docs in return
Partner.findOneAndUpdate(query,dataToUpdate,options,(err, document) => {
if (err) return err;
//console.log(document);
res.send({ document });
}
)
To set Deprecation Warnings on or off at mongoose level use option
mongoose.set('useFindAndModify', false)
Read more here:
Deprecation Warnings
findOneAndReplace
You can also use findByIdAndUpdate method:
Model.findByIdAndUpdate(id, update, options, callback)
You can enable promises to make code more readable and testable:
https://mongoosejs.com/docs/promises.html

Refering the doc, https://mongoosejs.com/docs/tutorials/findoneandupdate.html
first parameter of findOneAndUpdate should be a filter object, not the id directly.
So please try Partner.findOneAndUpdate({'_id': id},....

Related

How can i push into schema array of mongoose?Initial array is empy

I want to update array of objects - profiles by using input
I use express,mongoose in reactjs. I have schema --
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const validator = require("validator");
const { ObjectId } = mongoose.Schema.Types;
const userSchema = new mongoose.Schema({
email:{
type: String,
required: true,
minlength: 4,
unique: true,
validate: {
validator(email) {
return validator.isEmail(email);
},
},
},
password:{
type: String,
required: true,
minlength: 5,
select: false,
},
profiles:[ // array of user's profile
{
type:ObjectId,
name:String,
}
]
})
this is my route ---
router.post('/createProfile', createProfile);
what i tryed ---
module.exports.createProfile = (req,res) =>{
const {name} = req.body;
console.log(name)
User.push(profiles,name)
.then((result)=>res.send(result))
.catch((err)=>console.log(err))
}
I dont know what the coreect way to use push. Do i need to use push? Is my chema for profiles OK?
First, you specified in your schema that profiles field is of type array of ObjectIds. It looks like you want it to be of type String instead, since you are trying the push the name inside.
So, you should first change your Schema model:
profiles:[ // array of user's profile
{
type: String,
}
]
Now, you can push new items to that array like this:
User.updateOne(
{ _id: req.user._id },
{ $push: { profiles: name } }
)
you can use the %push operator in moongose
module.exports.createProfile = (req, res) => {
const { name } = req.body;
User.findOneAndUpdate(
{ _id: req.user._id },
{ $push: { profiles: { name } } },
{ new: true, useFindAndModify: false }
)
.then((result) => res.send(result))
.catch((err) => console.log(err))
};
the findOneAndUpdate function is used to find user. and update it .as you asked

{"index": 0,"code": 11000,"keyPattern": {"Name": 1}, "keyValue": { "Name": null }} error on adding second product to database

On trying to add a product to my database using the following method,
//ADD PRODUCT
router.post("/addproduct", verifyTokenAndAdmin, async (req, res) => {
const newProduct = new Product(req.body);
try {
console.log("req for pdt add");
const savedProduct = await newProduct.save();
console.log("pdt added successfully");
res.status(200).json(savedProduct);
} catch (err) {
res.status(500).json(err);
}
});
Mongoose is throwing this error when adding the second product. The first product is successful always but cannot make a second post request and also put request to update the product details is not working, but the delete request works perfectly fine
{
"index": 0,
"code": 11000,
"keyPattern": {
"Name": 1
},
"keyValue": {
"Name": null
}
}
Given below is my product schema
const { default: mongoose } = require("mongoose");
const ProductSchema = new mongoose.Schema(
{
title: { type: String, required: true, unique: true },
desc: { type: String, required: true },
img: { type: String, required: true },
category: { type: Array, required: true },
size: { type: String },
color: { type: String },
price: { type: Number, required: true },
},
{ timestamps: true }
);
module.exports = mongoose.model("Product", ProductSchema);
Because in your MongoDB field "name" have Properties UNIQUE at the field "Indexes". And you have to drop that property or you never can create the same name value even if it a empty value.
I used to have the same error, and this is my resolution for the issue:
This error comes as a result of a model waiting to receive data that should actually come from the body of the request, but because it cannot read it because you did not add the middleware app.use(express.json()). Therefore, it creates the index but without all the data.

How to update a field-List in MongoDB using Mongoose and Nodehs?

Hello dear Stackoverflow team.
I am trying to patch a user, which can handle several "devices". I am using nodeJs with Express and Mongoose (MongoDB). My User model is the following:
const userSchema = new Schema({
name: {type: String, required: true},
lastname: {type: String, required: true},
email: {type: String, required: true, trim: true, lowercase: true, unique:
true},
password: {type: String, required: true, minlength: 5},
userTyp: {type: String, required: true,
enum: {values: ['Administrator', 'Doctor','Patient','Optiker'], message:
'{VALUE} is not supported' }},
image: {type: String},
devices: [ {device: {type: Schema.Types.ObjectId, ref: "Device"}} ]
});
and I want to have something like this everytime i do a patch:
{
"user": {
"_id": "6138cd30ffc5239bba72e6c0",
"name": "Fernando",
"lastname": "Gonzalez",
"email": "f.gonzalez#unitransferklinik.de",
"password": "Hol087+/*",
"userTyp": "Administrator",
"image": "sdsadsadsa/asdfasdas",
"devices": [
{
"device": "6138c7587ab4b5fc4d369230"
},
{
"device": "6138c7587ab4b5fc4d365210"
}
],
}
}
How can I implement in my function:
const updateUser = async (req, res, next) => {
const { name, lastname, email, password, userTyp, device } = req.body;
const userID = req.params.userID;
let updatedUser;
try {
updatedUser = await User.findById(userID);
}catch(err){
console.log(err);
return next(new HttpError('Something happend.', 500));
}
updatedUser.name = name;
updatedUser.devices = [device, ...updatedUser.devices];
try{
updatedUser.save();
}catch (err) {
return next(new HttpError('It could not uodate device.', 500));
}
});
res.status(200).json({user: updatedUser.toObject( {getters: true} )});
};
In easy words, I want to updated the list everytime that i do a patch with a new device, and I can fetch later all the device list per user.
Thanks a lot!
regards,
Eliot
You can use findOneAndUpdate function of mongoose library
const dynamicModel = libMongoose.model(collection_name, userSchema);
var filter = { userID: req.params.userID };
var update = { name: name, devices : [...device, ...updatedUser.devices]};
//callback approach
dynamicModel.findOneAndUpdate(filter, update, (err, resp) => {
if(err) {
console.log("Error while updating record " + JSON.stringify(err));
}
if(!resp) {
console.log("Couldn't find record");
} else {
console.log("Updated data to DB");
}
});
You can also refer here for async await, Hope this helps!

In Mongoose findOneAndUpdate, how can I make my post request work?

Hi all so I am trying to make a post request that increments a value if it already exists and if not it should create a new item.
router.post('/', auth, async (req, res) => {
try {
const { name, price, image } = req.body;
var query = { name },
update = { $inc: { count: 1 } },
options = { upsert: true, new: true,};
await CartItem.findOneAndUpdate(query, update, options, function (
err,
data
) {
if (err) {
const newItem = new CartItem({
user: req.user.id,
name: name,
price: price,
image: image,
});
const item = newItem.save();
res.json(item);
} else {
res.json(data);
}
});
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CartItemSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
name: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
count: {
type: Number,
},
image: {
type: String,
required: true,
},
});
module.exports = CartItem = mongoose.model('cartItem', CartItemSchema);
So there are two problems here that I cannot wrap my head around(Pretty new with MongoDb, did do my research).
I can get the count to increment, but it increments with 2 or even more instead of 1. (I know other users also experienced this)
If the item is already in the cart(name matches) I want a new item to be added which does happen, but it only adds the name, count and Id. I want it to add the user, name, price and image.
Would appreciate some assistance.
you should create your document with a default value equals to 0.
define count at your schema like the following:
count: {
type: Number,
default: 0
}
then use { $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }.
link to docs: https://docs.mongodb.com/manual/reference/operator/update/inc/

MEAN Stack - Update route not posting correctly

I have built a mean app but am having an issue with it posting a number value. I'm not sure if it is a mongoose validation error but for some reason mongoose can not upsert the number value but will when it is a string.
Here's the route:
//Edit A Site
router.put('/api/sites/:site_id', function(req, res) {
Site.findById(req.params.site_id, function(err, site) {
if (err) {
res.send(err);
} else {
if(req.body.ip) site.ip = req.body.ip;
if(req.body.domain) site.domain = req.body.domain;
if(req.body.wp) site.wp = req.body.wp;
if(req.body.host_name) site.host_name = req.body.host_name;
if(req.body.hosted) site.hosted = req.body.hosted;
console.log(req.body);
// save the site
site.save(function(err) {
if (err)
res.send(err);
res.json(site);
});
}
});
});
The console.log has the full request body:
{ hosted: 1, host_name: 'sup', wp: 'n/a' }
But this is the mongoose response: Mongoose: sites.update({ _id: ObjectId("57a16c4a7f7e5b7a7e1f5ad1") }, { '$set': { host_name: 'sup', wp: 'n/a' } })
Schema:
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var sitesEntrySchema = new Schema({
ip: {
type: String,
required: true,
trim: true
},
domain: {
type: String,
required: true,
trim: true
},
wp: {
type: String,
required: true,
trim: true
},
host_name: {
type: String,
required: true
},
hosted: {
type: Number,
min: 0,
max: 1,
required: true
}
});
// make this available to our users in our Node applications
var Site = mongoose.model('Site', sitesEntrySchema);
module.exports = Site;
EDIT:
I believe I found the solution. When checking for the req.body.hosted, because it is a number it fails. I had to update to check for undefined:
if(req.body.hosted != undefined) site.hosted = req.body.hosted;

Resources