MongoDB using NodeJS api return Null why? - node.js

I know there is a lot of post about that but none have my problem, my tables exist, the path work to some extent but two of the request just return null and I have no idea why.
Here the request that dont work :
// *Get Chat Message*
router.get("/message/:MessageId",async(req, res)=>{
try{
const message = await Message.findById(req.params.MessageId);
res.status(200).json(message)
} catch (err){
res.status(500).json(err)
}
})
// *Get All Chat Message*
router.get("/message/findAll",async(req, res)=>{
try {
const messages = await Message.find();
res.status(200).json(messages)
} catch (err) {
res.status(500).json(err);
}
})
If need here is the rest of the file where ALL the requests work PERFECTLY so I don't know why only those two don't work.
const router = require("express").Router();
const Post = require("../models/Post");
const User = require("../models/User");
const Chat = require("../models/Chat");
const Message = require("../models/ChatMessage");
// * Get a Chat *
router.get("/:firstUserId/:secondUserId", async(req, res) => {
const chat = await Chat.findOne({ users: { $all: [req.params.firstUserId, req.params.secondUserId] } });
res.status(200).json(chat);
})
// * Get every Chat of one user *
router.get("/:userId", async(req, res) => {
try{
const chats = await Chat.find({ users: { $all: [req.params.userId]} });
res.status(200).json(chats);
}catch(err){
res.status(500).json(err);
}
})
// *Create Chat*
router.post("/",async(req, res)=>{
const chat = new Chat(req.body)
try {
const savedChat = await chat.save();
res.status(200).json(savedChat);
}catch(err){
res.status(500).json(err)
}
})
// *Delete Chat*
router.delete("/:firstUserId/:secondUserId",async(req, res)=>{
const chat = await Chat.findOne({ users: { $all: [req.params.firstUserId, req.params.secondUserId] } });
try{
chat.deleteOne();
res.status(200).json("The chat has been delete successfully.")
} catch (err){
res.status(500).json(err)
}
})
// *Put Chat Message*
router.put("/message",async(req, res)=>{
const newMessage = new Message(req.body)
try {
const savedMessage = await newMessage.save();
res.status(200).json(savedMessage)
} catch (err) {
res.status(500).json(err)
}
})
The schema name and parameter of the database are the same so I don't know why it doesn't work. It still returns null even if I erase the two that don't work, it only returns an error if I delete the whole file.
Here is my schema:
const mongoose = require("mongoose");
const ChatMessageSchema = new mongoose.Schema({
conversationId: {
type: String,
required: true
},
userId: {
type: String,
required: true
},
content: {
type: String,
required: true,
max: 5000
},
state: {
type: Number,
default: 0
}
},
{ timestamps: true }
);
module.exports = mongoose.model("chat_message", ChatMessageSchema,"chat_messages");
The table
Request done in Postman

to get all document use
Model.find({});
and for single try the following
Model.findOne({_id: <id>})

Finaly found the error.
The problem is that for express /message and /message/:MessageId were on the same path.
/findAll still does not work but I don't need it.

Related

Update items quantity in shopping cart in MongoDB (MERN Stack)

I have a function to add items to the shopping cart. Inside the function I have an if-else case. If the cart does not exist for that given user then it is created from scratch, otherwise (else case) if the cart already exists for that given user, then the key quantity must be updated to the specific itemId of that given item with the same Id.
In the function there is already the code block of the if case in case the cart does not exist. What can I do if I need to update the quantity of the Items?
Cart Schema
const mongoose = require('mongoose');
const idValidator = require('mongoose-id-validator');
const Schema = mongoose.Schema;
const cartItemSchema = new Schema ({
quantity: { type: Number, required: true },
itemId: { type: mongoose.Types.ObjectId, required: true, ref: 'Meal' }
});
const cartSchema = new Schema ({
cartItems : [
cartItemSchema
],
customer: { type: mongoose.Types.ObjectId, required: true, unique: true, ref: 'User',}
});
cartSchema.plugin(idValidator);
module.exports = mongoose.model('Cart', cartSchema);
Function
const addToCartByUserId = async (req, res, next) => {
const userId = req.params.uid;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return next(
new HttpError('Invalid inputs passed, check your data.', 422)
);
}
/* Find user in Database */
let user;
try {
user = await User.findById(userId);
} catch(err) {
const error = new HttpError('Creating cart failed, try again later.', 500);
return next(error);
}
if (!user) {
const error = new HttpError('Could not find user for provided id.', 404);
return next(error);
}
/* getCartByUserId */
let cart;
try {
cart = await Cart.find({ customer: userId });
} catch(err) {
const error = new HttpError('Something went wrong, could not find an user by its id.', 500);
return next(error);
}
// if cart doesn't exists. It works
if (!cart || cart.length === 0) {
const { cartItems } = req.body;
const createdCart = new Cart ({
cartItems,
customer: userId
});
try {
const session = await mongoose.startSession();
await session.withTransaction(async () => {
createdCart.save({ session });
});
session.endSession();
} catch(err) {
const error = new HttpError(
'Creating cart failed, please try again.',
500
);
console.log(err);
return next(error);
}
res.status(201).json({ cart: createdCart });
} else { // if cart already exists
let quantityToInsert = cart.cartItems[cartItems.itemId].quantity + cartItems.quantity;
cart.cartItems.push({
quantity: quantityToInsert
});
}
};

How to Delete document and sub documents referenced from others collections - MongoDB Mongoose

I have this collection Cart (cart schema) to delete and it is referenced with 2 other schemes, Meal and Customer (owner user, its schema is: User Schema).
How can I delete the cart by passing as req.params.id the user's id from the HTTP request?
Cart Schema
const mongoose = require('mongoose');
const idValidator = require('mongoose-id-validator');
const Schema = mongoose.Schema;
const cartItemSchema = new Schema ({
quantity: { type: Number, required: true },
itemId: { type: mongoose.Types.ObjectId, required: true, ref: 'Meal' }
});
const cartSchema = new Schema ({
cartItems : [
cartItemSchema
],
customer: { type: mongoose.Types.ObjectId, required: true, ref: 'User'}
});
cartSchema.plugin(idValidator);
module.exports = mongoose.model('Cart', cartSchema);
I created a function to delete the document, but it doesn't work, it returns the message: 'Deleted cart.', but isn't true, the document remains in collection.
const deleteCartByUserId = async (req, res, next) => {
const userId = req.params.uid;
let cart;
try {
cart = await Cart.find({ customer: userId });
} catch(err) {
const error = new HttpError('Something went wrong, could not delete cart.', 500);
return next(error);
}
if(!cart) {
const error = new HttpError('Could not find cart for this user id.', 404);
return next(error);
}
try {
Cart.deleteOne({ customer: userId });
} catch(err) {
console.log(err);
const error = new HttpError('Something went wrong, could not delete cart.', 500);
return next(error);
}
res.status(200).json({ message: 'Deleted cart.' });
};
So the porblem was that you missed an await before delete one function call.
Also I've changed some of youre code to make it cleaner:
const functionHandler = fn =>
(req, res, next) =>
Promise
.resolve(fn(req, res, next))
.catch(next);
const deleteCartByUserId = functionHandler(async (req, res) => {
const { params: { uid: userId } } = req;
const cart = await Cart.findOneAndDelete({ customer: userId })
if(!cart) {
throw new HttpError('Could not find cart for this user id.', 404);
}
res.status(200).json({ message: 'Deleted cart.' });
});
In your error handler middleware you can check for error type and if it's not HttpError use internal server error.

How to add to array in mongo db collection

Good evening,
I have my model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const widgetSchema = new Schema({
city: {
type: String
}
})
const userSchema = new Schema({
name: {
type: String,
},
password: {
type: String
},
widgets: [widgetSchema]
})
const User = mongoose.model('user', userSchema);
module.exports = User;
And my question is how can I add elements to the widget array?
Should I use an update or what?
I think, firstly I need to find user document:
app.post('/addwidget', async (req, res) => {
const { city } = req.body;
try {
const user = await User.findOne({"name": "1"});
}
catch(err){
console.log(err)
}
})
and thank what? Is there method like push or something like that?
Try this one :
try {
const user = await Research.findOneAndUpdate({ name: '1' }, { $push: { widgets: { city: 'viking' }} })
if (user) return user;
else return false;
} catch (error) {
console.log(error);
}
you can use $push or $addToSet to add new item to the widgets array :
app.post('/addwidget', async (req, res) => {
const { city } = req.body; //
try {
const user = await User.findOneAndUpdate({"name": "1"} , { $push: { widgets: city }});
}
catch(err){
console.log(err)
}
})
or :
app.post('/addwidget', async (req, res) => {
const { city } = req.body;
try {
const user = await User.findOneAndUpdate({"name": "1"} , { $addToSet : {widgets: city }});
}
catch(err){
console.log(err)
}
})
From the doc: Adding Subdocs to Arrays, you can use MongooseArray.prototype.push()
E.g.
app.post('/addwidget', async (req, res) => {
const { city } = req.body;
try {
const user = await User.findOne({ name: '1' });
user.widgets.push({ city: 'viking' });
await user.save();
} catch (err) {
console.log(err);
}
});

How to resolve post method which continues loading in postman

I'm new in Express.js,MongoDb and mongoose, I have created HTTP request methods, but when running the Post method, nothing done (nothing saved in the database), and postman continues loading and it stops only when I cancel.
I want to know what's wrong in my code, thank you .
this is my routes file 'department.js':
const express = require("express");
const router = express.Router();
const Department = require("../models/department")
router.get("/v1/departments", async (req, res) => {
try {
const departments = await Department.find({ isDeleted: false })
if (!departments) {
return res.status(404).send()
}
res.status(200).send()
} catch (error) {
res.status(500).send(error)
}
});
router.get("/v1/department/:id", async (req, res) => {
//test if the department exist => by id
const _id = req.params._id
try {
const depatment = await Department.findByid(_id, { isDeleted: false })
if (!depatment) {
return res.status(404).send()
}
res.status(200).send(depatment)
} catch (error) {
res.status(500).send(error)
}
});
router.post("/department", async (req, res) => {
const department = new Department(req.body) //this param is for testing the post methode by sending request from postman
try {
await department.save()
// res.status(201).send(department)
} catch (error) {
res.status(500).send(error)
}
});
router.put("/v1/department/:id", async (req, res) => {
//updates , allowedUpdates ,isValideOperations : those constants are used for checking if the updated fields exists or not !
//especially useful when testing the put method using postman
const updates = Object.keys(req.body)
const allowedUpdates = ['name', 'email']
const isValideOperations = updates.every((update) => allowedUpdates.includes(update)) //isValideOperations return true if all keys exists
if (!isValideOperations) {
return res.status(400).send({ error: 'Invalid updates' })
}
try {
const _id = req.params.id
const department = await Department.findByIdAndUpdate(_id)
if (!department) {
return res.status(404).send()
}
res.send(department)
} catch (error) {
res.status(500).send(error)
}
})
//Safe delete by updating the field isDeleted to true
router.delete('/v1/department/:id', async (req, res) => {
try {
const _id = req.params.id
const department = await Department.findByIdAndUpdate(_id, { isDeleted: true })
if (!department) {
return res.status(400).send()
}
res.status(200).send(department)
} catch (error) {
res.status(500).send(error)
}
})
module.exports = router
And this is the Model
const mongoose = require("mongoose");
const validator = require('validator')
const Department = mongoose.model('Department', {
name: {
type: String,
required: true,
}
,
email: {
type: String,
required: true,
trim: true,
lowercase: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Invalid email!')
}
}
}
,
createdBy: {
type: String,
default: 'SYS_ADMIN'
}
,
updatedBy: {
type: String,
default: 'SYS_ADMIN'
}
,
createdAt: {
type: Date
// ,
// default: Date.getDate()
}
,
updatedAt: {
type: Date
// ,
// default: Date.getDate()
},
isDeleted: {
type: Boolean,
default: false
}
})
module.exports = Department
this is Index.js (the main file)
const express = require("express");
const app = express()
const departmentRouter = require("../src/routes/department")
app.use(express.json())
app.use(departmentRouter)
//app.use('/', require('./routes/department'))
const port = process.env.PORT || 3000;//local machine port 3000
app.listen(port, () => (`Server running on local machine port ${port} 🔥`));
In order for you to get a response in Postman (or in an API call in general), you must actually send back a response, whether it's with sendFile, render, json, send, etc. These methods all call the built-in res.end which sends back data. However you commented out res.send which is the reason
I think you forget to add '/v1' in this route. it should be
router.post("/v1/department", async (req, res) => {
const department = new Department(req.body) //this param is for testing the post methode by sending request from postman
try {
await department.save()
// res.status(201).send(department)
} catch (error) {
res.status(500).send(error)
}
});

access the info of the user that created the post

I am making a react-native mobile app and I am having trouble passing the users info that created the post to the home page in the post detail. I can pass the userID but for some reason when I add the rest of the info to the payload I can't create a post. Please help.
BACKEND
This is the requireAuth file that requires authentication before performing a tast. My code for the user is here as well at the bottom---
const mongoose = require("mongoose");
const User = mongoose.model("User");
module.exports = (req, res, next) => {
const { authorization } = req.headers;
if (!authorization) {
return res.status(401).send({ error: "You must be logged in." });
}
const token = authorization.replace("Bearer ", "");
jwt.verify(token, "mySecretKey", async (err, payload) => {
if (err) {
return res.status(401).send({ error: "You must be logged in." });
}
const { userId, name, phone, email } = payload;
const user = await User.findById(userId);
req.user = user;
console.log(req.user);
next();
});
};
This is the POST route for the Item---
router.post("/items", requireAuth, async (req, res) => {
const { title, category, detail, condition, price } = req.body;
if (!title || !category || !detail || !condition || !price) {
return res.status(422).send({
error: "You must provide a title, category, detail, condition, and price"
});
}
try {
const item = new Item({
title,
category,
detail,
condition,
price,
userId: req.user._id
});
await item.save();
res.send(item);
} catch (err) {
res.status(422).send({ error: err.message });
}
});
FRONT-END
This is my createItem function in the itemContext file---
const createItem = dispatch => async ({
title,
category,
detail,
condition,
price
}) => {
try {
const response = await sellerApi.post("/items", {
title,
category,
detail,
condition,
price
});
//this is the other place the error might be happening i need this to save in the phone local storage
dispatch({ type: "create_item", payload: response.data });
navigate("Home");
} catch (err) {
console.log(err);
}
};
All I am trying to do it is when the post is being displayed so is the info of the post creator
For existing post in the database: If you are referencing your user in post model like this
const Post = mongoose.model('Post', {
// other fields
userId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
})
then you can use populate to fetch user of that post.
const post= await Post.findById('5c2e505a3253e18a43e612e6')
await post.populate('userId').execPopulate()
console.log(post.userId)

Resources