aknowledge:true but document is not updating with mongoose express - node.js

iam trying to update product quantity with matching ids in user cart
const productIds = []
const userCart = await Cart.findOne({owner:req.userId})
try{
for(i=0; i < user cart.item.length; i++){
productIds.push(userCart.item[i].product)
}
const update = await Products.updateMany({_id:productIds} , {$inc:{quantity:-1}}, {upsert:true}).catch(err => console.log(err))
console.log(update)
}catch(err){
console.log(err)
}

Related

Update and get lastest data in one function

I have the following javaScript code for Nodejs to update data in MongoDB.
I have a list of products that I want update (called itemsToBeUpdated). (Update the preference value in the order that they are passed-in)
Once all the updates have been completed, I would like to go and retrieve the product list by calling the function getProducts(req, res);
where should I put the getProducts(req, res)? Not position A because Product.findByIdAndUpdate is async so it will get to position A before the findByIdAndUpdate is completed.
Not position B because there are more items to loop through.
const updateAndRefreshProducts = (req,res) => {
const itemsToBeUpdated = req.body;
const counter = someValue
for(let i = 0; i<itemsToBeUpdated.length; i++){
const newPreference = counter;
counter++;
condition= {_id: itemsToBeUpdated[i]._id};
Product.findByIdAndUpdate(condition, {preference:newPreference})
.then(result => {
console.log('performing update completed for result' + result.name +" : ", result.preference);
//position B
})
.catch(error =>{
console.log('error', error);
});
}
//position A
}
thanks
There are a couple of way to handle this, the easiest way to accomplish this will be to utilize Promise.all().
You may want to read on this documentation
const updateAndRefreshProducts = (req,res) => {
const itemsToBeUpdated = req.body;
const productUpdatePromises = []
const counter = someValue
for(let i = 0; i<itemsToBeUpdated.length; i++){
const newPreference = counter;
counter++;
condition= {_id: itemsToBeUpdated[i]._id};
const productUpdatePromise = Product.findByIdAndUpdate(condition{preference:newPreference})
productUpdatePromises.push(productUpdatePromise)
}
await Promise.all(productUpdatePromises).then((results) => {
console.log(results);
//Called your get all products here
})
.catch((error) => {
console.error(error.message);
});
}

how to fetch subcollection's data in firestore?

I have built a webapp using node express to backend and for frontend I used Reactjs .
In firestore database has a "users" collection in there have many documents for every users. For each document have fields and have subcollections.
1st view
2nd view (in a subcollection view)
this is the sample database like my real database structure .I want fetch all users(inside the users table documents) andalso with subcollections fields.
For every users have same subcollections.(Like as this image user have 4 subcollections andaslo another user also have that same subcollections.)
For this I write the code like this.
model class
class Users {
constructor(id,name,email,provider,firstWord,leda,age,birthday,district,gender,familyChildren,fatherEducation,monthlyIncome,motherEducation,whichChild,awaSE,awaUN,kathakaraaSE,kathakaraaSE,kathakaraaUN) {
this.id = id;
this.name = name;
this.email = email;
this.provider = provider;
this.email = firstWord;
this.email = leda;
this.age = age;
this.birthday = birthday;
this.district = district;
this.gender = gender;
this.familyChildren = familyChildren;
this.fatherEducation = fatherEducation;
this.monthlyIncome = monthlyIncome;
this.motherEducation = motherEducation;
this.whichChild = whichChild;
this.awaSE = awaSE;
this.awaUN = awaUN;
this.kathakaraaSE = kathakaraaSE;
this.kathakaraaUN = kathakaraaUN;
}
}
module.exports = Users;
controller
'use strict';
const firebase = require('../db');
const Users = require('../models/users');
const firestore = firebase.firestore();
const getAllUsers = async (req, res, next) => {
try {
const users = await firestore.collection('users');
const data = await users.get();
const userArray = [];
if(data.empty) {
res.status(404).send('No user found');
}else {
data.forEach(doc => {
const users = new Users(
doc.id,
doc.data().name,
doc.data().email,
doc.data().provider,
doc.data().firstWord,
doc.data().leda,
doc.data().age,
doc.data().birthday,
doc.data().district,
doc.data().gender,
doc.data().familyChildren,
doc.data().fatherEducation,
doc.data().monthlyIncome,
doc.data().motherEducation,
doc.data().whichChild,
doc.data().awaSE,
doc.data().awaUN,
doc.data().kathakaraaSE,
doc.data().kathakaraaUN,
);
userArray.push(users);
});
res.send(userArray);
}
} catch (error) {
res.status(400).send(error.message);
}
}
module.exports = {
getAllUsers,
}
router class
const router = require("express").Router();
const { getAllUsers } = require('../controllers/userscontroller.js')
router.get('/AllUsers', getAllUsers);
module.exports = router;
model class image
1.users collection fields
2.childGrow collection fields
3.childPrivateDetails collection fields
4.familyDetails collection fields
5.wenath collection fields
but out put is
in there not display other collections fields.
How I do that using node express?
You can do something like this:
const getAllUsers = async (req, res, next) => {
try {
const users = await getFirestore().collection('users');
const data = await users.get();
const userArray = [];
if (data.empty) {
res.status(404).send('No user found');
} else {
for (let doc of data.docs) {
let firstSubCollectionData = await getFirestore().collection('users').doc(doc.id).collection('firstSubCollection').get();
let secondSubCollectionData = await getFirestore().collection('users').doc(doc.id).collection('secondSubCollectionData').get();
let thirdSubCollectionData = await getFirestore().collection('users').doc(doc.id).collection('thirdSubCollectionData').get();
let forthSubCollectionData = await getFirestore().collection('users').doc(doc.id).collection('forthSubCollectionData').get();
// construct your object here
// add it to list
}
res.send(userArray);
}
} catch (error) {
res.status(400).send(error.message);
}
}
BUT
sub-collections can be potentially a list of values. If not I think you have to redesign your data model.

Fetching Cart Products from the Server According to ID - Node.Js/Mongodb/Express

I tried to fetched data(more than one) from mongo db database according to the id and it doesn't work. I'll be thankful to you If you can help me to fix that issue.
static fetchCart(itemArr){
const userCart = [...itemArr]
const db = getDb();
const fetchedCart = [];
for (var i=0; i<userCart.length; i++){
const item = userCart[i];
db.collection("products")
.findOne({ _id: new mogoDb.ObjectId(item.productId) })
.then((prod) => {
fetchedCart.push(prod);
})
.catch((err) => {
console.log(err);
});
}
return fetchedCart;
}
Query for searching array of ids
db.collection.find( { _id : { $in : [1,2,3,4] } } );

Business logic works but Mongoose save doesn't

Hi I'm trying to save data from my shopping cart app to MongoDB database. In my cart controller folder, there are getAllProducts, addOneProduct, removeOneProduct and updateOneProducts methods. All of them run perfectly fine except for updateOneProducts.
The console.log shows:
GET all product { id: [1,2,4], qty: [1,1,1] }
UPDATE one product { id: [1,2,4], qty: [1,1,2] }
which indicate that the business logic works. However, the document is not updated on mLab.
User model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: String,
userID: String,
picture: String,
products: {
id: [Number],
qty: [Number],
}
});
const Users = mongoose.model('User', userSchema);
module.exports = Users;
updateOneProduct
const extractProduct = (user) => {
const product = {};
product.id = user.products.id;
product.qty = user.products.qty;
return product;
}
// if user is logged in n changes the qty of a product, update the qty in database
const updateOneProduct = (req, res) => {
// if (!req.user) return res.status(401).json({ error: 'Unauthorized' });
const userId = req.user._id;
const event = req.body.event;
const productId = req.body.id;
return Users.findById(userId)
.then(user => {
const qty = user.products.qty;
const index = user.products.id.indexOf(productId);
if (index === -1) {
throw new Error(`Product doesn't exist!`);
}
const regex = /^[0-9\b]+$/;
if (event === 'plus') {
qty[index] += 1;
} else if (event === 'minus') {
qty[index] -= 1;
} else if (regex.test(event) && event !== '0') {
qty[index] = Number(event);
}
if (qty[index] === 0) {
user.products.id.splice(index, 1);
qty.splice(index, 1);
}
return user.save();
})
.then(user => {
const product = extractProduct(user);
console.log('UPDATE one product', product);
return res.status(200).json(product);
})
.catch(error => res.status(400).json({ error }));
}
So I basically cloned user.products.qty array with const qty = [...user.products.qty], do operations on it and replace user.products.qty with it using user.products.qty = qty. Lastly, I save it with return user.save().
For some reason, I can't mutate subdocument project and save it. I have to replace the whole subdocument user.products then save for it to work. I think it might also have something to do with this being a PUT request.
// if user is logged in n changes the qty of a product, update the qty in database
const updateOneProduct = (req, res) => {
// if (!req.user) return res.status(401).json({ error: 'Unauthorized' });
const userId = req.user._id;
const event = req.body.event;
const productId = req.body.id;
return Users.findById(userId)
.then(user => {
const qty = [...user.products.qty];
const index = user.products.id.indexOf(productId);
if (index === -1) {
throw new Error(`Product doesn't exist!`);
}
const regex = /^[0-9\b]+$/;
if (event === 'plus') {
qty[index] += 1;
} else if (event === 'minus') {
qty[index] -= 1;
} else if (regex.test(event) && event !== '0') {
qty[index] = Number(event);
}
if (qty[index] === 0) {
user.products.id.splice(index, 1);
qty.splice(index, 1);
}
user.products.qty = qty;
return user.save();
})
.then(user => {
console.log('UPDATE - After save promise', user.products);
return res.status(200).json(user.products);
})
.catch(error => res.status(400).json({ error }));
}

How to Loop Data and Validate in Mongodb

I have a dynamic input field where user can add multiple category at once. Data sent at backend is like
['ELECTRONIC','TOYS','GAMES']
Now I want to check for each element of the array ,if they are already present on mongodb . If its present i want to store it in errors object as
errors={ 0: 'Duplicate Data found'}
I am attaching my code for validation which is not working please help . .
const Category = require('../../models/Category');
const fieldCheck = (req, res, next) => {
const data = req.body;
const errors = [];
for( i = 0; i < data.length ; i++){
Category.findOne({ category_name : data[i]})
.then(user => {
if(user){
// # If a reqistered User ID is found ,then move ahead
errors[i] = 'Duplicate Entry Found';
errors.push(errors[i]);
}
}).catch(err =>{
return res.json(err);
}
)
}
console.log(errors);
};
module.exports = fieldCheck;
My Category Schema is ....
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const categorySchema = new Schema ({
category_name:{
type:String,
unique:true,
isRequired:true,
},
date:{
type:Date,
default:Date.now()
}
});
module.exports = mongoose.model('Category',categorySchema);
You are trying to call an asynchronous method (findOne) inside a synchronous loop (for). As you experience, this is like oil and water.
An easy fix is to make your method asynchronous and use the await keyword, example:
const fieldCheck = async (req, res, next) => {
const data = req.body;
const errors = [];
try {
for( i = 0; i < data.length ; i++) {
let user = await Category.findOne({ category_name : data[i]});
if (user) {
// # If a reqistered User ID is found ,then move ahead
errors[i] = 'Duplicate Entry Found';
errors.push(errors[i]);
}
}
// I assume you wanted to respond to res.json here?
console.log(errors);
} catch (err) {
return res.json(err);
}
};
module.exports = fieldCheck;

Resources