Expense Tracker application : Nodejs, Mongodb
Trying to Create a function that will update only the passed fields from request inside an array of objects
Database Schema
const updateExpense = async (req, res) => {
try {
let db = mongo.getDb()
let { macro, micro, amount, note } = req.body;
let { username, id } = req.query
let expense = await db.collection("Expense").updateOne({ username: username, "expenses.expense_id": ObjectId(id) }, { $set: {
"expenses.$.macro": macro,
"expenses.$.micro": micro,
"expenses.$.amount": amount,
"expenses.$.note": note }
});
res.status(200).json({
message: "Expense Updated",
expense: expense
});
} catch (err) {
res.status(500).json({
message: err.message
});
}
}
The above function is replacing all other fields with null
If the user is passing only the micro field, then the other fields should remain the same and only the micro field should change and other fields should not change.
Need A MongoDB Query which will only change what is required based on the data passed in req
I think you must first fetch from the database with findOne then update that fields set in req.body, something like this:
const updateExpense = async (req, res) => {
try {
let db = mongo.getDb()
let { macro, micro, amount, note } = req.body;
let { username, id } = req.query
let expense = await db.collection("Expense").findOne({ username: username });
let special_ex = expense.expenses.find(ex => ex.expense_id === ObjectId(id);
special_ex.macro = macro ? macro : special_ex.macro;
special_ex.micro = micro ? micro : special_ex.micro;
/*
and so on ...
*/
await expense.update();
res.status(200).json({
message: "Expense Updated",
expense: expense
});
} catch (err) {
res.status(500).json({
message: err.message
});
}
}
Related
Let say we have a table called user and it has userId column.
user
----
userId
we have another table called Team and it has 2 columns userId and leadId.
Team
----
userId
leadId
condition 1:
I want to insert data into Teams table and that values, should be in user table. In other words userId and leadId of Teams table should of userId of user table. Otherwise it throws an error that id does not exists in user table.
condition 2:
one more condition is userId and leadId can't be same. This is done by using if check.
here is my API code
router.post('/', checkToken, async (req, res) => {
try {
const { body } = req;
const {
userId,
leadId
} = body
const dataToInsert = {
userId,
leadId
}
if (userId == leadId) {
res.status(300).json({ error: "Lead id and user can't be same." })
}
else {
const data = await db.Team.create(dataToInsert)
res.status(200).json({
data
})
}
} catch (e) {
console.log("Error in inserting team lead", e)
res.status(500).json({
error: "Internal Server Error",
status: false,
})
}
})
export default router;
Please help how to handle the condition 1.
update:
this is what i tried now
const IdCount= await db.User.findAll({
attributes: [[db.Sequelize.fn('count', db.Sequelize.col('id')), 'getIdCount']],
where: { "id": userId && leadId }
});
output of IdCount:
here is the output, the getIdCount value is 0 which is correct but it send me whole object, how i can get only getIdCount value?
[
user {
dataValues: { getIdCount: '0' },
_previousDataValues: { getIdCount: '0' },
_changed: Set(0) {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [Array]
},
isNewRecord: false
}
]
You just need to make sure both users exist in the Users table (execute two queries against the Users table) and then insert a record into the Teams table.
It's better to use an explicit transaction to get both users and insert a record into Teams.
To get either you have a user in DB you can use count:
const whereClause = userId ? {
where: {
id: userId,
}
} : {}
const userCount = await db.User.count({
where: {
id: userId
}
})
const userExists = count === 1;
The same way you can check leadId
here is what i have done, it giving me correct responses on all condtions
router.post('/admin/assign', checkToken, authorize('admin'), async (req, res) => {
try {
const { body } = req;
const {
userId,
leadId
} = body
const dataToInsert = {
userId,
leadId
}
const idCount = await db.User.count({ where: { [Op.or]: [{ id: userId }, { id: leadId }] } })
if (userId == leadId) {
res.status(400).json({ error: "Lead id and user can't be same." })
}
else if (idCount == 2) {
const data = await db.Team.create(dataToInsert)
res.status(200).json({
data
})
}
else {
res.status(400).json({ error: "UserId or LeadId doesn't exist" })
}
} catch (e) {
console.log("Error in inserting team lead", e)
res.status(500).json({
error: "Internal Server Error",
status: false,
})
}
})
export default router;
I have saved my data in MongoDB using mongoose. Now I want to get the 'quantity' field in cart and increment by 1.
Note : If you have better way to do it, Please help.
here is how the MongoDB Atlas collection looks like
Here is how iam doing it :
const User = require("../models/User");
exports.updateQuantity = async (req, res) => {
try {
const { userId } = req.body;
if (!userId) {
res.json("All fields are required");
}
let result = await User.findByIdAndUpdate(
userId,
{
$inc: {
"cart.$[inner].newProduct.quantity": 1,
},
},
{
new: true,
}
);
res.send({
success: true,
message: "Product has been incremented",
result: result,
});
} catch (error) {
console.log(error);
return res.status(500).json({
success: false,
message: "Something went wrong",
});
}
};
Getting this error:
You doing good, actually you need to get the right object since you are working in an array.
I see the cart could have multiple product so you need to find the right product by its id
Pass to your query another parameter to match the right object like this :
await User.findByIdAndUpdate({_id : userId, "cart.userId" : userId, "cart.newProduct._id" : productId })
Than you can increment by adding
$inc: {
"cart.newProduct.quantity": 1,
},
Maybe you won't have to put the "cart.userId" : userId in the filter if there aren't other userId
Hope it works !
Im trying to update the data , but its not updating in the database
but in console it is showing like this
Here is the code :
exports.forgotPassword = async( req, res) =>{
const { id, password } = req.body;
const user = await User.findOne({ _id : id })
if (!user) {
res.status(200).send({
message: "User was not found"
});
}
else {
const userUpdatedPassword = User.update({id}, {$set:{ password:encrypt(password),
updatedPasswordTime:new Date() }})
res.status(200).send({
message: "Upadted Sucessfully"
});
}
}
I think you put the wrong filter, you need to do const userUpdatedPassword = await User.updateOne({_id: id}, {$set:{ password:encrypt(password), updatedPasswordTime:new Date() }}), in addition you can await for result and print userUpdatedPassword to console to check if here updatedCount > 0.
I am new to Sequelize, and I'm trying to update an object, but it's not working. here is my code
const updateEmployee = async (req, res) =>{
let {full_name, email, phone_number, address} = req.body
const id = req.params.id;
Employee.findOne({
where: { id: id }
})
.then(employee => {
employee.update({
full_name: full_name.full_name,
email: email.email,
phone_number: phone_number.phone_number,
address: address.address
})
})
}
please assist !!
You can use the update() method and add the search scope as second argument. The update() method is a Promise that returns an array with with one or two elements. The first element is always the number of affected rows. See the sequelize API documentation for more details on the update() method.
Your code should look something like this. I have not tested this so you might need to tweak the code a bit:
updateUser: async (req, res) => {
try {
await employee.update(req.body, {
where: {
id: req.body.id
}
})
.then((result) => {
// check the first element in the array if there are rows affected
if (result[0] > 0) {
res.status(200).send({ message: 'data found' });
} else {
return res.status(422).send({ message: 'no data found' });
}
})
}
catch(error) {
console.log(error);
return res.status(500).send({ message: 'updating user failed' });
}
}
When you are using async function. It is best to use await also don't use promise based format this in below api first I am finding user with that id from database if its present it ill update user else it will throw error that there is no data with that id
updateUser: async (req, res) => {
try {
let data = await employee.findOne({
where: {
id: req.body.id
}
});
if (data) {
await employee.update(req.body, { where: { id: req.body.id } });
return res.status(200).send({message: data found});
}
else {
return res.status(422).send({message: no data found});
}
} catch (err) {
console.log(err)
return res.status(500).send({message: Internal server error);
};
}
GoodDay Experts,
I've tried following code but it did not work, and it gives me null value.. maybe my routes are wrong but basically it works the way on other routes... and here is my backend for delete case: manage.js/actions
export const removeRecipient = (payload) => async (dispatch) => {
try {
const res = await axios.delete(
`${_config.MAT_URL}/api/1/customer/delete`,
payload
);
dispatch({
type: DELETE_CUSTOMER,
payload: res.data,
});
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { err },
});
}
};
and for my routes which is the mongoose query for findOneAndDelete, under customer.js :
router.delete("/delete", (req, res) => {
Customer.findOneAndDelete({ _id: req.params.id }, (err, Customer) => {
if (!err) {
res.json({ msg: "customer deleted", deleted: Customer });
} else {
console.log("Error removing :" + err);
}
});
});
And for the front end im using "AiOutlineDelete" which was coded as :
const handleDelete = (id) => {
console.log('delete')
removeRecipient(id)
}
<a
id={`delete-${rowIndex}`}
className="anchor-action-delete"
href="#foo"
onClick={(e) => {
e.preventDefault();
handleDelete(row);
}}>
thanks have a great day
There are 2 problems in your code:
req.params.id is meant for urls of the form /delete/:id which is obviously not your route, you should change it to req.query.id instead which matches query parameters in the url such as /delete?id=123.
The default type of _id is ObjectId, under the assumption you did not change this you need to cast your req.query.id which is type string to ObjectId.
It looks like you're using mongoose so here's mongoose syntax:
const mongoose = require("mongoose");
router.delete("/delete", (req, res) => {
Customer.findOneAndDelete({ _id: new mongoose.Types.ObjectId(req.query.id) }, (err, Customer) => {
if (!err) {
res.json({ msg: "customer deleted", deleted: Customer });
} else {
console.log("Error removing :" + err);
}
});
});
For nodejs native Mongo package:
import {ObjectId} from "mongodb";
...
new ObjectId(req.query.id)
I dont see you sent the id to the backend but you are trying to retrieve it from req.params.id try passing the id like "delete/:id" at the end of the link and specify this in the routes aswell.
if that doesnt fix try the below code this for routes
if nothing works check this, In the component you need to send the id(object id) but i see "row" what is the value of row? if the row value is not the id in the database then it wont delete. if this your issue try inspecting the code by keeping breakpoints or write a console.log() to check the value of "row" .
try {
const removedProject = await Customer.remove({
_id: req.params.id
})
res.json(removedProject)
} catch (err) {
res.json({
message: err
})
}