I want to update a particular user's financial records which is an array.
<-- This is my user model -->
const FinanceSchema = new mongoose.Schema({
moneyToBePaid: {
type: Number,
},
moneyPaid: {
type: Number,
},
moneyToBeReceived: {
type: Number,
},
moneyReceived: {
type: Number,
},
});
const UserSchema = new mongoose.Schema({
financialInformation: [FinanceSchema],
});
module.exports = mongoose.model("user", UserSchema);
<-- This is my post route -->
router.post("/users/:id/profile", async (req, res) => {
const _id = req.params.id;
const {
moneyToBePaid,
moneyPaid,
moneyToBeReceived,
moneyReceived,
} = req.body;
const finance = {
moneyToBePaid,
moneyPaid,
moneyToBeReceived,
moneyReceived,
};
try {
const user = await User.findById(_id);
user.financialInformation.push(finance);
await user.save();
res.status(200).json(user);
}
<-- This is my update route -->
router.patch("/users/:user_id/profile/:profile_id", async (req, res) => {
const user_id=req.params.user_id;
const profile_id=req.params.profile_id;
try {
}
I am confused how to update a particular user's particular finance record.
Assuming you want to update the moneyPaid property of specific finance array element:
try {
const user_id=req.params.user_id;
const profile_id=req.params.profile_id;
await User.findOneAndUpdate(
{ "_id": user_id, "financialInformation._id": profile_id },
{
"$set": {
"financialInformation.$.moneyPaid": "2258" // the data you want to update
}
});
res.status(200).send('user updated');
} catch(err) {
console.log(err);
res.send(err);
}
Related
I am using Express.js, Node.js, MongoDB, and Mongoose stack
I have three documents in the database which are Warehouses, Inventories, and Items.
A Warehouse has one Inventory, and each Inventory is assigned to a Warehouse.
An Inventory contains many Items.
items.model.js
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
name:{
type: String
},
dateCreated:{
type: Date,
default: Date.now()
},
price:{
type:Number
},
type:{
type:String
},
category:{
type:String
},
description:{
type: String
},
picture:{
type: String
}
})
const Item = mongoose.model('item',itemSchema)
module.exports.Item=Item
module.exports.itemSchema = itemSchema
inventories.model.js
const mongoose = require('mongoose');
const itemSchema = require('../items/items.model').itemSchema;
const inventorySchema = new mongoose.Schema({
name:{
type: String,
unique: true
},
dateCreated:{
type: Date
},
items:{
type:[itemSchema]
}
})
const Inventory = mongoose.model('inventory',inventorySchema)
module.exports.inventorySchema=inventorySchema;
module.exports.Inventory=Inventory;
warehouses.model.js
const mongoose = require('mongoose');
const inventorySchema = require('../inventories/inventories.model').inventorySchema
const warehouseSchema = new mongoose.Schema({
name:{
type:String
},
location:{
type:String
},
inventory:{
type:inventorySchema
},
dateCreated:{
type:Date,
default:Date.now()
},
numberOfEmployees:{
type:Number
}
})
const Warehouse = mongoose.model('warehouse',warehouseSchema)
module.exports.Warehouse=Warehouse
I have an endpoint which assigns an Inventory to a Warehouse based on the Inventory's name. I also have an endpoint that adds an Item to an Inventory
warehouses.controller.js
/**
*
* Assign an inventory to warehouse based on
* Warehouse (id), inventory (name)
*/
const assignInventory = () => async (req, res) => {
try {
const inventoryName = req.body.inventory
const inventoryDoc = await Inventory.findOne({ name: inventoryName })
if (!inventoryDoc) {
return res.status(404).json('No Inventory with this ID exists!')
}
const warehouseID = req.params.id
const doc = await Warehouse.findByIdAndUpdate(
{ _id: warehouseID },
{ ...req.body, inventory: inventoryDoc }
)
if (!doc) {
return res.status(404).end()
}
return res.status(200).json({
message: 'Assigned Inventory to warehouse successfully',
data: doc
})
} catch (error) {
console.error(error)
res.status(400).end()
}
}
inventories.controller.js
/**
*
* Add an Item to an Inventory based on
* Inventory (id), Item (name)
*/
const addItemToInventory = () => async(req,res)=>{
try {
//Retreive the inventory id from the URL Parameters
const inventoryID= req.params.id
//Retreive the item name from the request body
const itemName= req.body.name;
//Fetch the item document from the database based on the request body
const itemDoc = await Item.find({name:itemName})
if(!itemDoc)
{
return res.status(404).json(`Can't find item with this name`)
}
console.log(itemDoc)
//Update the inventory with the the new item document added to its item list
const inventoryDoc = await Inventory.findById({_id:inventoryID})
console.log(inventoryDoc)
var inventoryList = inventoryDoc.items
console.log('Updated')
inventoryList.push(itemDoc)
console.log(inventoryList)
const updatedInventoryDoc = await Inventory.findByIdAndUpdate({_id:inventoryID},{$push:{items:itemDoc}})
if(!updatedInventoryDoc){
return res.status(404).end()
}
res.status(200).json({data: updatedInventoryDoc})
} catch (e) {
console.error(e)
}
}
The problem is that whenever I add an Item to an Inventory that is already assigned to a Warehouse, if I fetched that Warehouse, it will not show the added Item.
In the image above, I added an Item to the Inventory and fetched that Inventory.
The Inventory was previously added to a Warehouse.
Yet as seen above here, The Warehouse still has only one item inside it.
Is there anything that can reference an Inventory inside a Warehouse? so that after any update to any Inventory, the Warehouse will listen to these updates.
Thanks in advance.
Edit 1: Added Inventory, Warehouse, and Item models.
After searching I found out that I should change the structure of the warehouse.model.js to make it referring to the ObjectID of an Inventory, so it is going to look like this.
const mongoose = require('mongoose');
const inventorySchema = require('../inventories/inventories.model').inventorySchema
const warehouseSchema = new mongoose.Schema({
name:{
type:String
},
location:{
type:String
},
//Instead of inventory:inventorySchema
inventory:{
type: mongoose.Schema.Types.ObjectId,
ref: "inventory"
},
dateCreated:{
type:Date,
default:Date.now()
},
numberOfEmployees:{
type:Number
}
})
const Warehouse = mongoose.model('warehouse',warehouseSchema)
module.exports.Warehouse=Warehouse
and inside the warehouses.controller.js, we should call populate on any database call that retrieves the Warehouse documents like this
const readWarehouse = () => async (req, res) => {
try {
const doc = await Warehouse.find({}).populate('inventory')
if (!doc) {
return res.status(404).end()
}
res.status(200).json({ data: doc })
} catch (e) {
console.error(e)
res.status(400).end()
}
}
const readOneWarehouse = () => async (req, res) => {
try {
const id = req.params.id
const doc = await Warehouse.findOne({ _id: id }).populate('inventory')
if (!doc) {
return res.status(404).end()
}
res.status(200).json({ data: doc })
} catch (e) {
console.error(e)
res.status(400).end()
}
}
Also updated the assignInventory() to be like that
const assignInventory = () => async (req, res) => {
try {
const inventoryName = req.body.inventory
const inventoryDoc = await Inventory.findOne({ name: inventoryName })
if (!inventoryDoc) {
return res.status(404).json('No Inventory with this ID exists!')
}
const inventoryDocID=inventoryDoc._id
const warehouseID = req.params.id
const doc = await Warehouse.findByIdAndUpdate(
{ _id: warehouseID },
{ ...req.body, inventory: inventoryDocID }
)
if (!doc) {
return res.status(404).end()
}
return res.status(200).json({
message: 'Assigned Inventory to warehouse successfully',
data: doc
})
} catch (error) {
console.error(error)
res.status(400).end()
}
}
can this be done with fetch api which method should i use post or put? please reply.. can someone please give me the complete api to push orderSchema as a subdocument in userSchema i have scrolled tons and tons of links still i am not able to find any answer too this
this is the schema i am using in mongo db.
import mongoose from 'mongoose'
const orderSchema = new mongoose.Schema({
rsph: { type: Number },
rcyl: { type: Number },
raxis: { type: Number },
lsph: { type: Number },
lcyl: { type: Number },
laxis: { type: Number },
add: { type: Number },
frame: { type: String },
lens: { type: String }
}, {
timestamps: true
});
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
phone: { type: Number, required: true },
address: { type: String, required: true },
orders: [orderSchema]
}, {
timestamps: true
});
export default mongoose.models.User || mongoose.model('User', userSchema)
I am using this api to save userschema and this is working.
import initDB from '../../helper/initDB';
import User from '../../models/addUser';
initDB()
export default async (req, res) => {
(req.method)
{
"POST"
await handler(req, res)
}
}
const handler = async (req, res) => {
if (req.method == 'POST') {
console.log(req.body)
const { name,phone,address } = req.body
let u = new User( {name,phone,address } )
await u.save()
res.status(200).json({ success: "success" })
}
else {
res.status(400).json({ error: "this method is not required" })
}
}
I am using this api to save this data as a subdocument but this api is not working what changes should i make?
import initDB from '../../../helper/initDB';
import User from '../../../models/addUser';
initDB()
export default async (req, res) => {
(req.method)
{
"POST"
await handler(req, res)
}
}
const handler = async (req, res) => {
if (req.method == 'POST') {
console.log(req.body)
const { uid } = req.query
const user = await User.findOne({ _id: uid })
const { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens } = req.body
const order = ({ rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens });
user.orders.push(order);
await user.save()
res.status(200).json({ success: "success" })
}
else {
res.status(400).json({ error: "this method is not required" })
}
}
please reply...
Remove bracket () from the below line.
const order = ({ rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens });
only pass the object, as
const order = { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens };
The final should be as:
const handler = async (req, res) => {
if (req.method == 'POST') {
console.log(req.body)
const { uid } = req.query
const user = await User.findOne({ _id: uid })
const { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens } = req.body
const order = { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens };
user.orders.push(order);
await user.save()
res.status(200).json({ success: "success" })
}
else {
res.status(400).json({ error: "this method is not required" })
}
}
Im trying to create an API where users can create their fav movies and rate them.
So instead of creating a Movies array in user model, I created a Movie model with userId as an array. Now the logic is if there is a movie by the same name the new user is trying to create, it will not create a movie, rather it will push the userid and their rating. If there is no movie by that name it will create one. But I am stuck in that part. Any help will be hugely appreciated. Below im posting my code.
Movie model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const movieSchema = new Schema({
title: {
type: String,
required: true,
},
rating: [
{ type: Number, required: true, max: 5 },
],
userId: [
{
type: String,
},
],
});
const Movie = mongoose.model(
'Movie',
movieSchema
);
module.exports = Movie;
user model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
required: true,
},
age: {
type: Number,
required: true,
},
// list: {
// type: Array,
// default: [],
// },
});
const User = mongoose.model('User', userSchema);
module.exports = User;
movie route
const router = require('express').Router();
const User = require('../models/User');
const Movie = require('../models/Movies');
//creating a movie
router.post(
'/:id/createmovie',
async (req, res) => {
const { title, rating } = req.body;
const userId = req.params.id;
try {
const currentMovie = await Movie.findOne({
title,
});
if (currentMovie == null) {
const newMovie = new Movie({
title,
rating,
userId,
});
newMovie
.save()
.then((data) => res.json({ data }))
.catch((err) => {
res.status(400).json({ error: err });
});
}
currentMovie
.updateOne(
{ title },
{ $push: { userId, rating } }
)
.then((data) => res.json({ data }))
.catch((err) => {
res.status(400).json({ error: err });
});
} catch (err) {
console.log(err);
}
}
);
// router.post('/:id/createmovie', (req, res) => {
// const { title, rating } = req.body;
// const userId = req.params.id;
// Movie.findOne({ title }).then((data) => {
// console.log(data);
// res.json(data);
// if (data == null) {
// res.send('true');
// }
// res.send('false');
// if (data.title == title) {
// Movie.updateOne(
// { title },
// { $push: { userId, rating } }
// );
// }
// const newMovie = new Movie({
// title,
// rating,
// userId,
// });
// newMovie
// .save()
// .then((data) => res.json({ data }))
// .catch((err) => {
// res.status(400).json({ error: err });
// });
// });
// });
router.get('/getmovie', (req, res) => {
const { title } = req.body;
Movie.find({ title })
.then((data) => res.json(data[0].title))
.catch((err) => {
res.status(400).json({ error: err });
});
});
module.exports = router;
Change router.post function arguments
router.post(
'/:id/createmovie',
async (req, res) => {
const { title, rating } = req.body;
const userId = req.params.id;
try {
const currentMovie = await Movie.findOne({
title,
});
if (currentMovie == null) {
await Movie.insertOne({title ,rating, userId})
.
}
else{
await Movie.updateOne(
{ title },
{ $push: { userId, rating } }
)
}
} catch (err) {
console.log(err);
}
}
);
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);
}
});
exports.clearHours = (req, res, next) => {
Hour
.find({ user: req.body.userId })
.then(hour => {
for (let i=0;i<hour.length;i++) {
hour[i].hours = 0;
}
return hour.save()
})
.then(result => {
res.status(200).json({message: 'Working hours have been successfully updated.'});
})
.catch(err => {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
})
};
I am trying to save the formatted array on the database and I get this error. The updated code is passed properly but when I am trying to save the array it comes up with this error. Any ideas why?
This is my hour model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const hourSchema = new Schema ({
day: {
type: String,
required: true
},
hours: {
type: Number,
required: true
},
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
}
});
module.exports = mongoose.model('Hour', hourSchema);
It seems you are fetching the document into memory and re-setting the hour field to 0, better you can run an update query into the database itself.
On top require mongoose -
const mongoose = require('mongoose');
Below is clearHours method refactored.
exports.clearHours = async (req, res, next) => {
try {
const query = {
user: mongoose.Types.ObjectId(req.body.userId)
};
const update = {
$set: {
hours: 0
}
};
await Hour.update(query, update).exec();
res.status(200).json({message: 'Working hours have been successfully updated.'});
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};