I'm getting an error running router.patch() code to update a product on a cloud-based mongoose database. I'm using Postman to simulate the update. Postman's error is showing, "req.body[Symbol.iterator] is not a function." Here is the relevant code:
Products.js:
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Product = require('../models/product');
router.patch('/:productId', (req, res, next) => {
const id = req.params.productId;
// don't want to update both fields if not needed
const updateOps = {};
// loop through all the operations of the request body
for (const ops of req.body) {
updateOps[ops.propName] = ops.value;
}
Product.update({_id: id}, { $set: updateOps })// $set is a mongoose object
.exec()
.then(result => {
console.log(result);
res.status(200).json(result);
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
{req.body.newName, price, req.body.newPrice} ;
res.status(200).json({
message: 'Updated product',
});
});
module.exports = router
Product.js:
const mongoose = require('mongoose');
const productSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: String,
price: Number
});
// export the schema into the Mongoose model
module.exports = mongoose.model('Product', productSchema);
Any help would be greatly appreciated. :-)
As I commented, this part is likely your problem:
for (const ops of req.body) {
updateOps[ops.propName] = ops.value;
}
Since req.body is an Object, I think you want:
for (let [key, value] of Object.entries(req.body)){
updateOps[key.propName] = value;
}
Or something similar.
Related
I have a little problem to understand that how to solve this error.i am just a beginner to nodejs and mongodb/mongoose.I am creating a component in reactjs to update any particular documents using its user_id which i am passing a params in routes.
there is the code:
const express = require('express');
const mongoose = require('mongoose');
const mongodb = require('mongodb')
const user = require('../schema');
const router = express.Router();
router.get('/:id', function (req, res) {
const userid = {
userid: (req.params.id || '')
}
console.log('getting to be updated data');
user.db1.findOne(userid, function (err, data) {
if (err) throw err
res.send(data)
console.log(data)
});
});
module.exports = router
//here is the user model:
const userSchema = new mongoose.Schema({
userid:{type:String},
fullname:{type:String},
phone:{type:Number},
email:{type:String},
})
const skillSchema = new mongoose.Schema({
userid:{type:Number},
skills:{type:String},
})
const users = mongoose.model('users',userSchema);
const skills = mongoose.model('skills',skillSchema);
module.exports ={
db1 : users,
db2 : skills
}
I guess you haven't specified in the find.one () function by which parameter it will search. Try it by typing your own column name instead of id.
user.db1.findOne({ id: userid } ,function(err, data){
if (err) throw err
res.send(data)
console.log(data)
});
Or you can change your function and use findById().
user.db1.findById(userid, ,function(err, data){
if (err) throw err
res.send(data)
console.log(data)
});
am playing with MongoDb and Mongoose, and I am trying to filter by price range, for example display properties from 0 to any number (10000),
My model is very simple:
const mongoose = require('mongoose');
const PropertySchema = mongoose.Schema({
title: String,
description: String,
price: Number,
town: String
})
module.exports = mongoose.model('Property', PropertySchema);
And route. this what am up to, set price from 0 to any number, I don’t want to hard-code this max value
const express = require('express');
const router = express.Router();
const Property = require('../models/Property');
router.get('/', async (req, res) => {
try {
const properties = await Property.find({ price: { $in: [ 0, 0 ] } });
res.json(properties);
} catch (err) {
res.json({ message: err });
}
});
URL
properties?price=0&10000
Can anybody help me with this? How can I set range of price for properties?
You need to pass both priceMin & priceMax from queryParams & use same in your query
const express = require('express');
const router = express.Router();
const Property = require('../models/Property');
router.get('/', async (req, res) => {
try {
const properties = await Property.find({ price: { $gte:req.query.priceMin, $lte: req.query.priceMax } });
res.json(properties);
} catch (err) {
res.json({ message: err });
}
});
URL
properties?priceMin=0&priceMax=10000
You can do this using $gt and $lt
properties?min=0&max=10000
router.get('/', async (req, res) => {
let min = req.query.min;
let max = req.query.max;
try {
const properties = await Property.find({ price: { $gt : min , $lt : max } });
res.json(properties);
} catch (err) {
res.json({ message: err });
}
});
I make an axios request from the frontend through node to a Mongodb database requesting a userName based on userId. The request comes back as having been made, but no data is returned.
This is the Mongodb users collection:
{
"_id" : ObjectId("5e1b46cb2e6f4c98904598b0"),
"userId" : "foo#baz.com",
"userName" : "Fool",
}
This is the 'Users' schema file
users model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
userId: String,
userName: String,
});
module.exports = mongoose.model('Users', UserSchema);
This is the backend request:
backend:
const express = require('express');
const UserRoute = express.Router();
const Users = require('../Models/UserModel');
UserRoute.route('/fetchUserName').get(function (req, res) {
Users.find({userId: req.query.userId}, {userName: 1})
.exec(function (err, user) {
if (err) {
console.log(err);
res.json(err);
} else {
console.log(user.data);
res.json(user.data);
}
});
});
Here is the actual request from the frontend:
getUserName = () =>
axios.get('http://localhost:4000/Users/fetchUserName', {params: {userId: 'foo#baz.com'}})
.then(res => {
return res.data;
});
};
res.data is returned as an empty string.
Any ideas why the request does not work.
The userId should probably send as a string.
So either:
const params {
userId: 'foo#baz.com'
}
axios.get('http://localhost:4000/Users/fetchUserName', { params })
or
axios.get('http://localhost:4000/Users/fetchUserName', {params: {userId: 'foo#baz.com'}})
I developed my node rest api as usual but this time it is showing some invalid error in controller.js file. The mongoose is not getting required. When I hit the API in postman, it gives the error as :
{
"error": {
"message": "Tweets is not a constructor"
}
}
I even updated my packages for the same, but nothing seems to work. Here is the snippet of my controller for tweets.js:
const mongoose = require('mongoose');
const Tweets = require('../models/tweets');
exports.get_all_tweets = (req, res, next) => {
Tweets.find()
.exec()
.then(docs => {
console.log(docs);
res.status(200).json(docs);
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}
exports.create_tweets = (req, res, next) => {
const tweetbody = req.body;
tweetbody._id = mongoose.Types.ObjectId();
const tweet = new Tweets(tweetbody);
tweet
.save()
.then(docs => {
console.log(docs, 'Tweets');
res.status(200).json(docs);
})
.catch(err => {
console.log(err, 'error found');
res.status(500).json({
error:err
});
});
The first mongoose line is appearing blank as shown in the screenshot:
mongoose
Model for tweets.js:
const mongoose = require('mongoose');
const tweetSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
time: { type: String},
count: { type: Number}
});
module.export = mongoose.model('Tweets', tweetSchema);
please check all path and add new keyword before schema initializing
Model for tweets.js:
const tweetSchema = new mongoose.Schema({
Try this using async/await
exports.get_all_tweets = async (req, res, next) => {
const result = await Tweets.find()
res.status(200).json(result);
}
module.exports with a 's' at the end :)
I've come across a blocker on attempting to promisify a mongoose method.
As far as my understanding goes I should be able to promisify fn's that take in callbacks with an error and a parameter, but in this case I get this error:
TypeError: this.Query is not a constructor
model code:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema({
name: String,
password: String,
admin: Boolean
}));
breaking code:
var User = require('./app/models/user');
var { promisify } = require('util');
var findUserPromise = promisify(User.findOne);
...
findUserPromise({ name: req.body.name })
.then(user => console.log("do something with the user"))
.catch(err => { console.log("err ", err) });
Any help is very much appreciated!
mongoose is already very promise-friendly. To get a promise from findOne(), you just need to call .exec():
Instead of
var findUserPromise = promisify(User.findOne);
...
findUserPromise({ name: req.body.name })
.then(user =>
...
Just call it with .exec()
:
User.findOne({ name: req.body.name }).exec()
.then(user =>
...
Yes as #Jim B answer, mongoose is promise friendly. you can also use async and await
const User = require('./app/models/user');
module.export = {
userDetails: async (req, res, next) => {
try {
const user = await User.findOne({ name: req.body.name });
console.log(user);
}
catch(err) {
console.log(err);
}
}
}