Store Product Detail in an array using mongoDB - node.js

import mongoose from 'mongoose'
const Register_user = mongoose.Schema({
Gender : String,
name : String,
dob : String,
weight : String,
height : String,
userEmail : String,
cart : Array
})
const register_schema = mongoose.model("User_registration" , Register_user)
export default register_schema;
// ^ Add to Cart
export const addToCart = async (req,res) =>
{
try {
// ^ Product Data (actually item data that user added to cart) now need to save this in cart array
const Data = req.body.item;
// ^ to match user Email and cart Data in only and only his cart array
const email = req.body.userEmail;
// ^ finding User based on email
const user = await registerSchema.findOne({userEmail : `${email}`})
if(user)
{
// ^ successfully got the user and his cart
const {cart} = user;
}
} catch (error) {
console.log(`error in adding item to cart + ${error.message}` )
}
}
I want to store item details in cart Array , whatever item user added to cart i want to store it in mongodb cart[] is there a specific method to do this? I tried safe() doesn't work for me

I fixed it by getting an id of a document and using the findByIdAndUpdate method.
if (user) {
// ^ successfully got the user and his cart
const { _id } = user;
console.log(_id);
const { cart } = user;
await registerSchema.findByIdAndUpdate(_id, { cart: [...cart, Data] }).then('done babe');
}

Related

Mongoose Trouble Adding Subdocs to Array

I am looking to push to an array on my users schema in mongoose. I am following mongoose's Adding Subdocs to Arrays documentation but keep getting an error on user.notes.push(newNotebook)
TypeError: Cannot read properties of undefined (reading 'push')
Here is my setup:
const User = require('../models/userModel')
const addNotebook = async (req, res) => {
...
const user = User.findOne({ userId })
const newNotebook = { userId: userId, notebookId: notebookId, title: title, numNotes: 0 }
user.notebooks.push(newNotebook)
}
Any help would be much appreciated.
Update--
Here is the solution:
const User = require('../models/userModel')
const addNotebook = async (req, res) => {
...
const user = User.findOne({ userId })
if (!user) return
const newNotebook = { userId: userId, notebookId: notebookId, title: title, numNotes: 0 }
user.notebooks = user.notebooks || []; // returns user.notebooks if defined else empty array
user.notebooks.push(newNotebook)
await user.save()
}
Big thanks to Mandeep for showing me the !user condition and .save() method. Special thanks to Sardar for bringing the user.notebooks = user.notebooks || [] solution to light.
Disclaimer: upon watching this video on MongoDB anti patterns, I learned nesting boundless data under a single document can be problematic since each MongoDB document is limited to 16mb. It is also supposedly inefficient relative to saving your data in respective collections. Use caution when adding subdocs to arrays.
It would be like this:
const addNotebook = async(req, res) => {
const user = await User.find({
userId
}).limit(1).exec()
if (!user) return
const newNotebook = {
userId: userId,
notebookId: notebookId,
title: title,
numNotes: 0
}
user.notebooks.push(newNotebook)
await user.save()
}
This is probably caused because "notebooks" is undefined by default for your userModel/schema
You can resolve this by two methods
const User = require('../models/userModel')
const addNotebook = async(req, res) => {
...
const user = User.find({
userId
})
const newNotebook = {
userId: userId,
notebookId: notebookId,
title: title,
numNotes: 0
}
user.notebooks = user.notebooks || []; // returns user.notebooks if defined else empty array
user.notebooks.push(newNotebook)
}
RECOMMENDED
Or you can set default value for notebooks in your userModel like this (might not update your existing user documents)
How to set default value in schema mongoose?

Auto increment in MongoDb is not working in Express NodeJS

exports.addToCart = async(req,res)=>{
const cart = await schema.cart.findOne({username:req.body.username})
if(cart){
return res.status(404).json({
message:"User's cart is already available, append to the same cart"
})
}
else{
const cart = new schema.cart({
cartId : getValueForNextSequence("item_id"),
username : req.body.username,
productsInCart :req.body.productsInCart
});
console.log(cart.cartId);
await cart.save();
res.status(200).json(cart)
}
}
async function getValueForNextSequence(sequenceOfName){
const sequenceDoc = await schema.counter.findOneAndUpdate(
{"_id": sequenceOfName },
{"$inc":{"sequence_value":1}},
);
return sequenceDoc.sequence_value;
}
THis is the schema for counter I added a document with _id as item_id and sequence_value as 0
const counterSch = new mongoose.Schema({
_id :{
type : String
},
sequence_value:{
type : Number
}
})
getValueForNextSequence method is not returning any value I dont know why please help with this issue.Here I have to increment the cartId automatically but its not happening

Not able to find the right Document

I am a working on a project for my school. I want to delete employees in the database. This can be done by setting the attribute isDeleted to true.
isDeleted : {
type : Boolean,
default :false,
required : true
}
and the controller function:
const deleteEmployee = async(req, res)=>{
try{
const employeeID = req.body.id;
console.log(employeeID);
const employee = await Member.findByIdAndUpdate(employeeID, {isDeleted : true}, {new : true});
res.status(200).json(employee)
}catch(err){
console.log(err);
}
}
I am not able to update the database. Please suggest changes.

Auto-generate employee ID using mongoose and nodejs

I'm working on a web app project using MEAN stack technology. I want to generate 'empId' (employee ID) automatically when a request to add a new employee is received. How can I do the same and store the generated 'empId' in the same document where I keep employee details?
Thanks in advance!
Unless there are other requirements that haven't been stated, you can simply generate empId when handling the request to add a new employee, and include it with other properties that may be supplied by the caller:
const schema = new Schema({ name: String, empId: String });
const Employee = model('Employee', schema);
// then when handling an "add employee" request:
const { name } = req.body; // properties from request
const empId = generateEmployeeId(); // e.g., "uuid()"
const employee = new Model({name, empId})
You can also automatically include an empId with each new Document by supplying it as a default in the mongoose Schema. Combine that with a library like nanoid (that gives you a bit more control over the ids generated) and you would have something like:
const schema = new Schema({
name: String,
empId: {
type: String,
default: () => nanoid()
}
})
Also keep in mind that mongodb will always create a unique identifier for each document in the _id property.
I solved the code using nanoid and presave feature of mongoose.
The code below generates a user friendly id that can be used for many different utilities.
The only potential issue is if the loop keeps finding same id due to the huge amount of users in db(this should not be an issue most apps), this issue can be reduced by either increasing the size of custom alphabets or by just adding more custom characters.
import mongoose from 'mongoose'
import { customAlphabet } from 'nanoid/async'
const schema = new mongoose.Schema({ name: String, empId: String });
const Employee = mongoose.model('Employee', schema);
employeeSchema.pre('save', async function (next) {
if (this.isNew) {
const nanoid = customAlphabet('1234567890abcdefABCDEF', 10)
let unique = true
let id = ''
while (unique) {
id = await nanoid()
const user = await Employee.findOne({ empId: id })
if (!user) {
unique = false
}
}
this.empId = id
}
next()
})

How to send query parameters with axios to backend

I am trying to send a string and number values upon hitting submit which is to be stored in a database collection (log collection).
I am making use of the MERN stack. I have tried sending it vis Axios, but when I console log the "req.params" in the backend, I get undefined. why am I not getting the typed in value of "order" at the backend? I am sure there is something I am not doing right, but I can figure it out. I need help.
handleSubChange(id, quantity){
// these lines of code below gets the inputted values and then subtracts from the total quantity
if ((parseInt(quantity) - parseInt(this.state.minus))<0) {
alert('The input value is too high.');
}else{
var nums = parseInt(quantity)-parseInt(this.state.minus);
// and just before I send the value of "nums" via Axios, I get the user to type in destination for the item and add the inputted value of "order" on the Axios URL
const order = prompt("Please enter item destination")
axios.get("/api/inventory/add_product/" + id + "/" + nums + "/" + parseInt(quantity) + "/" + order)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
})
}
}
Here is the backend route
router.get("/add_product/:id/:num/:quantity/:order",(req,res) => {
var id = req.params.id;
var quantity = req.params.quantity;
//i then console log req.params.order, i get undefined
console.log(req.params.order)
// console.log('id----', id);
var num_mod = req.params.num;
var modified_count = parseInt(num_mod) - parseInt(quantity);
console.log('num_mod----', num_mod);
Inventory.findByIdAndUpdate(id,{quantity: parseInt(num_mod)},{new:true},function(err,inventory){
if (err){
console.log("err",err);
res.status(500).send(err);
} else {
console.log(inventory.name);
console.log(inventory.order)
const newLog = new Log({
name:inventory.name,
description:inventory.description,
price:parseInt(inventory.price),
quantity:parseInt(inventory.quantity),
modified_quantity: parseInt(modified_count),
order:inventory.order,
});
newLog.save(function(err, Log) {
if (err){
console.log(err);
} else{
console.log('add log success');
res.send(inventory);
}
});
}
});
});
Inventory model
const mongoose= require('mongoose');
//create Schema
const InventorySchema = new mongoose.Schema({
// _id: mongoose.Schema.Types.ObjectId,
name : { type: String, required: true },
description : { type: String, required: true },
price : { type: Number, required: true },
quantity : { type: Number, required: true },
supplier : String,
taxable : Boolean,
order:String,
// Create model from the schema
const Inventory = mongoose.model("Inventory", InventorySchema);
// Export model
module.exports = Inventory;
The issue is your backend route definition, which is missing a / before :order.
router.get("/add_product/:id/:num/:quantity:order",(req,res) => {
// ^ missing /
Change to:
router.get("/add_product/:id/:num/:quantity/:order",(req,res) => {
// ^ correct

Resources