Api Post 400 Bad Request - javascript

I'm making a post API on a dummy node project; it worked fine there, but implemented the same API on the main project I got the 400 Bad request error while running this API on a post.
Route js
router.post("/add",(req, res) => {
const planName = req.body.planName;
const planPrice = req.body.planPrice;
const planMode = req.body.planMode;
const planStatus = req.body.planStatus;
const newAddon = new Addon({
planName,
planPrice,
planMode,
planStatus,
});
console.log("newAddon", newAddon)
newAddon.save()
.then(() => res.json("Addon added"))
.catch(err =>
res.status(400).json("Error in Add Addon route")
);
});
Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const addonsSchema = new Schema(
{
planId: {type: Number,required: true},
planName: {type: String,required: true},
planPrice: {type: Number,required: true},
planMode: {type: String, required:true},
planStatus: {type: String, required:true}, //active or inactive
},
{timestamps: true},
);
const Addon = mongoose.model("Addons", addonsSchema);
module.exports = Addon
index.js
const addonRouter = require('./routes/addon')
app.use('/addons',addonRouter)
Postman Screenshot

You'll need to provide planId as well in the payload, since you've defined required as true.
You've 2 ways to solve this:
Set the value of planId equal to _id field that mongodb creates automatically before inserting. You can do this with a preSave hook on the model.
addonsSchema.pre("save", (next) => {
// only triggered when creating new records
if (this.isNew) {
this.planId = this._id;
}
next();
});
And your type for planId should be ObjectId.
planId: {type: ObjectId,required: true},
Won't recommend but you can remove required attribute from planId.

Related

How can I get the value of this array in MongoDB?

How can I get the value of this array
const { model, Schema} = require("mongoose")
let ticketSchema = new Schema({
GuildID : String,
MembersID: [String],
TicketID: String,
ChannelID: String,
Closed: Boolean,
Locked: Boolean,
Type: String,
Claimed: Boolean,
ClaimedBy: String,
Open:Boolean,
OpenBy:String,
})
module.exports = model("Ticket", ticketSchema);
Example:
{
_id: new ObjectId("63d8340e0a415466f7ad55f0"),
GuildID: '1066373193767592047',
MembersID:
[0]:811664013313310720
TicketID: '2',
ChannelID: '1069728239200780398',
Closed: false,
Locked: false,
Type: 'Hola',
Claimed: false,
Open: false,
OpenBy: '811664013313310720',
__v: 0
}
How can I get the value of MembersID:[0]:811664013313310720 in this case it would be 811664013313310720 I need it to check on a system
Try methods with findOne, Find
I assume you use MongoDB Driver and the following syntax can extract the property MembersID
data = await dbo.collection(COLLECTION).find({},{projection:MembersID:1}).toArray()
MongoDB Drivers → Node.js
const MongoClient = require('mongodb').MongoClient;
const config = require('../config/mongodb'); // Your Own Connections Details
let db, dbo;
const COLLECTION = 'Ticket';
db = await MongoClient.connect(config.url, config.connection);
dbo = await db.db(config.database);
let data = [];
const options = {
projection: { MembersID: 1 }
};
data = await dbo.collection(COLLECTION).find({}, options).toArray();
data[0].MembersID // Access the Array
Mongoose
data = await dbo.collection('Ticket').find({}).exec();
Point to Note
The MembersID is a type of Integer, ensure you have right type when comparing
The MongoDB client connection details is omitted. MongoDB Connect to DB Official Document
Mongoose Refer to this document Mongoose find

how to pass the collection name dynamically in the mongoDB schema

Now can you guys please help me with how can I pass the dynamic value while creating the Schema? I want to modify the {CollectionName} in Schema.But I don't want to update the .env file again and again.
I want to pass it as a param
const CardSchema = new mongoose.Schema({
collectionName: {
type: String,
required: true,
}
});
console.log(tabelName);
module.exports = mongoose.model(`${CollectionName}`, CardSchema);
app.post("/form", async (req, resp) => {
const userCard = new CardSchema({
collectionName: req.body.collectionName,
cardName: req.body.cardName,
cardIndex: req.body.cardIndex,
content: req.body.content,
label: req.body.label,
});
await userCard.save();
console.log("user added");
resp.send(userCard);
});
'I did this but I don't think it is the best way
const CollectionName = process.env.COLLECTION_NAME;
'

req.body undefined from react client to express server

Server: NodeJS, Express, Mongoose/MongoDB
Cloud provider: MongoDB
Client: React, mobx, axios
Tested with: body-parser, express.json()
Short question:
Controller requests data(string) - userId on certain URL from client, but req.body.userId is always undefined. I've checked every component and console logged every step and every react functional component prop - it's okay.
Everything else works fine, such as: find user on sign in/create on sign up, finding posts by id, adding comments to certain post using is id and so all.
Already looked up 10-15 questions about this issue, nothing helped. I need to know in which of these files I've been dumb. Thanks in advance!
Additional info:
Part of server/index.js file:
const app = express()
app.use(corsMiddleware)
app.use(express.json()) //also the body-parser returns the same result
app.use('/api/user', userRouter)
CORS middleware:
function cors(req, res, next) {
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Methods", "GET, PUT, PATCH, POST, DELETE, OPTIONS")
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, Origin, X-Requested-With, Accept, X-Auth-Token")
if (req.method === "OPTIONS") {
res.status(200)
}
next()
}
User model:
const {Schema, model} = require('mongoose')
const User = new Schema({
email: {type: String, required: true, unique: true},
login: {type: String, required: true},
password: {type: String, required: true},
link: {type: String, required: true},
avatar: {type: String},
bio: {type: String},
status: {type: String, default: 'offline'},
friends: {type: Array, default: []},
communities: {type: Array, default: []},
requests: {type: Object, default: {
to: [],
from: []
}},
posts: {type: Array, default: []},
settings: {type: Array, default: []},
registrationDate: {type: String, default: Date.now()}
})
module.exports = model('User', User )
Post model:
const {Schema, model} = require('mongoose')
const moment = require('moment')
const Post = new Schema({
title: {type: String, required: true},
content: {type: String, required: true},
userId: {type: ObjectId, required: true, ref: 'User'}, //problem here
login: {type: String, ref: 'User'},
likes: {type: Array, default: []},
dislikes: {type: Array, default: []},
comments: {type: Array, default: []},
date: {type: String, default: () => {
return moment().format('D/MM/YYYY hh:mm')
}}
})
module.exports = model('Post', Post )
Part of userController that gets request:
async getUserById(req, res) {
try {
const {userId} = req.body //tried also const userId = req.body.userId
console.log(userId) //for debugging, output undefined
const user = await User.findById(userId)
res.status(200).json(user)
console.log(user) //for debugging, output null
} catch (e) {
console.log(e) //no errors
}
}
}
Part of user.routes:
router.get('/get', userController.getUserById)
//also deleted the authMiddleware for now, just to make things clean
Client components relations: Feed -> Post -> UserModel
Part of Feed.jsx:
const renderPosts = () => {
return(
posts.map((post) => {
return (
<Post
key={post._id}
username={post.login}
title={post.title}
text={post.content}
likes={post.likes}
dislikes={post.dislikes}
comments={post.comments}
date={post.date}
id={post._id}
userId={post.userId} //problem here
/>
)
})
)
}
Part of Post.jsx:
const [userId, setUserId] = useState('')
useEffect(() => {
console.log(`user id passed from Feed ${props.userId}`) //output OK
setUserId(props.userId)
console.log(`user id as prop in Post ${userId}`) //output OK
}, [props.userId]) //I know I don't need to put it to dependencies, just testing
return (
<div className={styles.Post}>
<div className={styles['post-user']}>
<UserModel userId={userId} username={props.username} link='#'/>
<p className={styles['post-user-title']}>{props.title}</p>
</div>
</div>
)
Part of UserModel.jsx:
export default function UserModel(
{
username,
link,
reverse,
mainUser,
onClick,
comment,
isFriend,
userId
}) {
const handleUsernameClick = async () => {
userPage.fetchUserData(userId)
console.log(`model user id ${userId}`) //output is OK
}
return (
<div className={styles['user-model']}
{//some unnecessary data here with button that calls handleUsernameClick}
</div>
)
}
Part of mobx file that holds fetchUserData method:
class UserPage {
constructor() {
makeAutoObservable(this)
}
//some methods here
fetchUserData = async(userId) => {
try {
const user = await axios.get('http://localhost:5000/api/user/get',
{userId},
{
headers:{Authorization: `Bearer ${localStorage.getItem('token')}`},
})
this.user = user
this.setUserPage(
user.login,
user._id,
user.link,
user.friends,
user.communities
)
console.log(user)
console.log(`user id in store ${userId}`) //output OK
} catch (e) {
console.log(e)
}
}
}
}
export default new UserPage()
to send data, you need to use POST method
change it throughout:
router.post('/get', userController.getUserById)
await axios.post('http://localhost:5000/api/user/get',

TypeError: Cannot use 'in' operator to search for 'userId'

So i was implementing a users model in my mvc and then i get a weird error saying
MongoClient constructor.
D:\node\node_modules\mongoose\lib\document.js:2022
if (path in this.$__.selected) {
^
TypeError: Cannot use 'in' operator to search for 'email' in saifkhan501721#gmail.com
at model.isSelected (D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2022:14)
at D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2195:14
at Array.filter (<anonymous>)
at _getPathsToValidate (D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2194:71)
at model.Document.$__validate (D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2365:23)
at D:\node\node_modules\←[4mkareem←[24m\index.js:369:33
←[90m at processTicksAndRejections (internal/process/task_queues.js:79:11)←[39m
i have no idea as to what is the reason behind the error is, is it a syntax error , logical error connection error or mispelling of a variable,well anyway here's my app.js
mongoose
.connect('mongodb+srv://turd_waffle:SaifKhan#cluster0.lltqs.mongodb.net/shop?retryWrites=true&w=majority')
.then((result) => {
User.findOne().then(user=>{
if(!user){
const user=new User({
name:'Saif',
email:'saifkhan501721#gmail.com',
cart:{
items:[]
}
})
user.save()
}
})//save() saves the documents(mostly used as a reference to generate a sample id in order to start a cluster working)
app.listen(3000)
})
.catch(err => {
console.log(err)
})
here's my user.js model to store users data in mongodb database
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
cart: {
items: [{
productId: {
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: {
type: Number,
required: true
}
}]
},
})
userSchema.methods.addToCart = function(product) {
const cartProductIndex = this.cart.items.findIndex(cp => {
return cp.productId.toString() === product._id.toString();
})
let newQuantity = 1;
const updatedCartItems = [...this.cart.items];
if (cartProductIndex >= 0) {
newQuantity = this.cart.items[cartProductIndex].quantity + 1;
updatedCartItems[cartProductIndex].quantity = newQuantity
} else {
updatedCartItems.push({
productId: product._id,
quantity: newQuantity
})
}
const updatedCart = {
items: updatedCartItems
}
this.cart=updatedCart
return this.save()
}
module.exports = mongoose.model('User', userSchema)
can anyone please be kind enough to atleast tell me what the error above is trying to say i used app.use to create a user so i can store his id, email and name
app.use((req, res, next) => {
User.findById('5f788c080ba19e0f8c642202')
.then(user => {
req.user = new User(user.name, user.email, user.cart, user._id);
next();
})
.catch(err => console.log(err));
});
Strange issue. From the code you provided, the issue should not arise.
When I look at the code in mongoose, the only way that this could happen is if you would do something like:
new User("saifkhan501721#gmail.com")
Then this.$__.selected would be a string instead of an object (e.g. {email: "saifkhan501721#gmail.com"}) and path in this.$__.selected would cause your received type error.
Not knowing enough about your app, I would assume that there maybe is a bad User object created somewhere else / cached / or already in database. Maybe it would help to verify this using a clean database?
See the source code for reference. When I take a look at the code it seems like an oversight that it is not checked if this.$__.selected is a string, because in this case it does not fail early (e.g. Object.keys(this.$__.selected) will not cause an error).

How add a listener to remove a function in MongoDB?

I'm trying to 'listen' the remove envent in a MongoDB schema named Post. Once the user removes one post, that haves one image on AmazonWeb Cloud, I have to remove this image from the cloud. My problem is that this listener doesn't work, maybe it's outdated; I need some alternative to this code.
Here the code of the schema (PostSchema):
//imports
const mongoose = require('mongoose');
const aws = require('aws-sdk');
const fs = require('fs');
const path = require('path');
const { promissify } = require('util');
//using AWS's lib
const s3 = new aws.S3();
//Schema declaration
const PostSchema = new mongoose.Schema({
name: String,
size: Number,
key: String,
url: String,
createdAt: {
type: Date,
default: Date.now
}
});
//listener to all 'save' events (it works)
PostSchema.pre('save', function() {
if(!this.url) {
this.url = `${process.env.APP_URL}/files/${this.key}`
}
});
//LISTENER THAT NOT WORKS
PostSchema.pre('remove', function() {
//if the storage type defined is AWS, delete image from AWS
//else, delete from local storage
if(process.env.STORAGE_TYPE == 's3') {
return s3.
deleteObject({
Bucket: 'upload-example-nodeapp',
Key: this.key
})
.promise()
} else {
return promissify(fs.unlink)(
path.resolve(__dirname, '..', '..', 'tmp', 'uploads', this.key)
);
}
});
If you use something like Model.remove to remove the document you have to use the { query:true } option
schema.pre('remove', { query: true }, function() {
console.log('Removing!');
});
by default it uses the { document: true } option ant the hook only fires when you use doc.remove. This is all writen in the documentation

Categories