How to waiting while document updating in mongoose? - node.js

I have this code:
module.exports = async (msg) => {
const postId = msg.wall.copyHistory[0].id;
const userId = msg.wall.ownerId;
const bonusePostManager = new BonusePostManager(postId)
const post = await bonusePostManager.getPost(postId);
if (!post) return;
if (post.reposters.includes(userId)) return;
const balanceManager = new BalanceManager(userId, 0);
const doubleCheckReposter = await bonusePostManager.getPost(postId);
if (doubleCheckReposter?.reposters.includes(userId)) return;
bonusePostManager.addReposter(userId)
.catch(console.error)
.then((res) => {
balanceManager.plusBalance(post.bonuseAmount, 'balance').then(async (res) => {
await messageAssistant.sendMessage({
peer_id: userId,
text: `Вы сделали репост, вы получаете ${numberWithSpace(post.bonuseAmount)}`
})
})
})}
If a person makes a repost from two devices at the same time, then the document does not have time to update and allows the possibility of a double repost. I tried using the $addToSet operator:
addReposter(userId, postId = this.postId) {
return Bonuse.updateOne({
id: postId,
}, {
$addToSet: {
'reposters': userId
}
})
}
But it doesn't help, I really don't know how to fix it. I return the promiss everywhere, try to wait for them, but this does not fix the situation, please help me!
I also attach the BonusePost scheme:
const { Schema } = require('mongoose');
const PostSchema = new Schema({
postId: {
type: Number,
unique: true,
index: true
},
active: {
type: Boolean,
default: true,
index: true,
},
bonuseAmount: {
type: Number,
},
reposters: {
type: Array,
default: [],
}
})
module.exports = PostSchema;
And model:
const { model } = require('mongoose');
const PostSchema = require('./schema');
const Bonuse = new model('Bonuse', PostSchema)
module.exports = Bonuse;

Related

insert an array of object ids mongoose nodejs

I want to be able to post several Object id's into the array,, I have two models control and subcontrol is referenced in the control model as an array. The idea is a control number might have sub control number under it
My post method:
router.post(
'/add',
auth,
role.checkRole(role.ROLES.Admin, role.ROLES.Regulator),
async (req, res) => {
try {
const subControls = []
for(const subControl of req.body.subControls){
const tableSubControl ={
subControlNo: subControl.subControlNo
};
const newSubControls = new SubControl(tableSubControl);
const subControlDoc = await newSubControls.save();
const control = new Control({...req.body, subControl: subControlDoc._id});
const savedControl = await control.save();
subControls.push(newSubControls)
}
res.status(200).json({
success: true,
message: `Control has been added successfully!`,
control: savedControl
});
} catch (error) {
return res.status(400).json({
error
// error: 'Your request could not be processed. Please try again.'
});
}
}
);
Control Schema:
const ControlSchema = new Schema({
_id: {
type: Schema.ObjectId,
auto: true
},
mainControl: {
type: String
},
subControl: [
{
type: Mongoose.Schema.Types.ObjectId,
ref: 'SubControl'
}
],
controlDescription: {
type: String,
trim: true
},
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('Control', ControlSchema);
My subControl schema:
const SubControlSchema = new Schema({
_id: {
type: Schema.ObjectId,
auto: true
},
subControlNo: {
type: String
},
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('SubControl', SubControlSchema);
Postman:
{
"mainControl": "1-1",
"subControls":
[
{
"subControlNo": "1-2-1"
},
{
"subControlNo": "1-2-2"
}
],
"controlDescription": "controldescription"
}
I'm not getting any clear error,, any idea what I need to do?
Well I am guessing when you create new Control object from req.body then don't set subControl:subcontrol._id there. Instead a object subcontrol should be assigned to Control object.
const subControlDoc = await newSubControls.save();
const control = new Control({...req.body});
control.subcontrol = subControlDoc
const subControlDoc = await newSubControls.save();
const savedControl = await control.save();
subControls.push(newSubControls)
We can manage this using Population :
Consider the following changes in the code, I have tried adding comments too.
router.post(
"/add",
auth,
role.checkRole(role.ROLES.Admin, role.ROLES.Regulator),
async (req, res) => {
try {
//first create a single control document
const control = new Control({
mainControl: req.body.mainControl,
controlDescription: req.body.controlDescription,
});
//nitpick: the for loop below can be made async.
for (const subControl of req.body.subControls) {
const tableSubControl = {
subControlNo: subControl.subControlNo,
};
const newSubControls = new SubControl(tableSubControl);
const subControlDoc = await newSubControls.save();
//save the looped subControl document
control.subControls.push(subControlDoc);
//push the association to the control document.
}
//save the control document, moved outside the loop
const savedControl = await control.save();
res.status(200).json({
success: true,
message: `Control has been added successfully!`,
control: savedControl,
});
} catch (error) {
return res.status(400).json({
error,
// error: 'Your request could not be processed. Please try again.'
});
}
}
);

ObjectParameterError: Parameter "filter" to find() must be an object, got search

this get route is giving no error in post-man but doing the same with frontend giving error in node console:
ObjectParameterError: Parameter "filter" to find() must be an object, got search
although response are fetched.
get controller
const Recent = require("../models/recent");
const getRecentByName = async (req, res, next) => {
const name = req.params.name;
let regex = new RegExp(name, "i");
let players;
try {
players = await Recent.find({ name: { $regex: regex } });
} catch (err) {
return next(err);
}
if (!players) {
return next("no player found");
}
// console.log(players);
res.json({ players });
};
exports.getRecentByName = getRecentByName;
fetching from frontend:
const searchRecords = async () => {
const data = await sendRequest(
"http://localhost:5000/api/player/recent/search/" + search,
"GET"
);
setRecord(data.players);
};
Recent:(mongoose Schema):
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const recentSchema = new Schema({
name: { type: String, required: true },
recent: [
{
team1: { type: String },
team2: { type: String },
points: { type: Number, required: true },
date: { type: Date },
},
],
});
module.exports = mongoose.model("Recent", recentSchema);
I think the problem is from the front and in the URL
you should use
http://localhost:5000/api/player/recent/search/${search}

Tools to create a functional Shopping Cart

I'm creating an e-commerce using Reactjs for frontend and Nodejs for backend (also express), and i want to create an shopping cart "connected" to the user account, where the user can recharge the page, close it, and the cart doesn't reset.
I'm looking for tools to create this, or some tutorial to do it with node-express, thanks! (i don't have code yet, cause i don't know from where starts)
This is User Model with Cart( with add-to-cart and remove from cart Function )
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
resetToken: String,
resetTokenExpiration: Date,
cart: {
items: [
{
productId: {
type: Schema.Types.ObjectId,
ref: "Product",
required: true,
},
quantity: {
type: Number,
required: true,
},
},
],
},
});
userSchema.methods.addToCart = function (product) {
const cartProductIndex = this.cart.items.findIndex((cp) => {
return cp.productId.toString() === product._id.toString();
});
let newQuantity = 1;
const updatedCartItems = [...this.cart.items];
if (cartProductIndex >= 0) {
newQuantity = this.cart.items[cartProductIndex].quantity + 1;
updatedCartItems[cartProductIndex].quantity = newQuantity;
} else {
updatedCartItems.push({
productId: product._id,
quantity: newQuantity,
});
}
const updatedCart = {
items: updatedCartItems,
};
this.cart = updatedCart;
return this.save();
};
userSchema.methods.removeFromCart = function (productId) {
const UpdatedCartItems = this.cart.items.filter((item) => {
return item.productId.toString() !== productId.toString();
});
this.cart.items = UpdatedCartItems;
return this.save();
};
userSchema.methods.clearCart = function () {
this.cart = { items: [] };
return this.save();
};
module.exports = mongoose.model("User", userSchema);
Here, Routes
router.get("/cart", (req, res, next) => {
req.user
.populate("cart.items.productId")
.then((user) => {
const products = user.cart.items;
// console.log(products);
res.render("home/cart", {
path: "/cart",
pageTitle: "Your cart",
products: products,
isAuthenticated: req.session.isLoggedIn,
});
// console.log(products);
})
.catch((err) => {
console.error(err);
});
});
router.post("/cart",(req, res, next) => {
const prodId = req.body.productId;
// console.log(prodId);
Product.findById(prodId)
.then((product) => {
return req.user.addToCart(product);
})
.then((result) => {
// console.log(result);
res.redirect("/cart");
});
});
Tech:-
Frontend:- Ejs View Engine
Backend:- Express, MongoDB Atlas

trying to assign value to schema in schema in mongoose in nodejs

so my mongoose model looks like this
userName:{
type:String,
required:true
},
userEmail:{
type:String,
required:true
},
userGym: gySchema,
userPassword:{
type:String,
required:true
}
gySchema is another schema and through patch method of https I am trying to assign a value to a variable in gySchema in Nodejs, how can I do so??
Below is the code for your reference as I too have done a project using this. When your using patch you have to just use req.body as it is what you want to update. and the route will be req.patch. patch is for partial update. put is for entire update.
model
const Joi = require("joi");
const mongoose = require("mongoose");
const { Genre, validateGenre, genreSchema } = require("./genre");
Joi.objectId = require("joi-objectid")(Joi);
const movieSchema = new mongoose.Schema({
title: {
type: String,
required: true,
minlength: 5,
maxlength: 50,
},
numberInStock: {
type: Number,
required: true,
min: 0,
max: 255,
default: 13,
},
dailyRentalRate: {
type: Number,
min: 0,
max: 255,
required: true,
},
liked: {
type: Boolean,
default: false,
},
genre: {
type: genreSchema,
required: true,
},
});
const Movie = mongoose.model("Movie", movieSchema);
function validateMovie(movie) {
const schema = {
title: Joi.string().required().min(5).max(255),
numberInStock: Joi.number().required().min(0).max(255),
dailyRentalRate: Joi.number().required().min(0).max(255),
liked: Joi.boolean(),
genreId: Joi.objectId().required(),
_id: Joi.objectId(),
};
return Joi.validate(movie, schema);
}
module.exports.Movie = Movie;
module.exports.validateMovie = validateMovie;
routes
const express = require("express");
const { Movie, validateMovie } = require("../models/movie");
const { Genre } = require("../models/genre");
const auth = require("../middlewares/auth");
const admin = require("../middlewares/admin");
const validateObjectId = require("../middlewares/validateObjectId");
const router = express.Router();
router.get("/", async (req, res) => {
const movies = await Movie.find();
res.send(movies);
});
router.post("/", async (req, res) => {
//validate the movie
const { error } = validateMovie(req.body);
if (error) {
console.log(error);
return res.status(400).send(error.details[0].message);
}
const genre = await Genre.findById(req.body.genreId);
if (!genre) {
return res.status(400).send("No genre found with given id");
}
const movie = new Movie({
title: req.body.title,
numberInStock: req.body.numberInStock,
dailyRentalRate: req.body.dailyRentalRate,
liked: req.body.liked,
genre: {
_id: genre._id,
name: genre.name,
},
});
// console.log(movies);
await movie.save();
console.log("Saving the document...");
res.send(movie);
});
//updating
router.put("/:id", async (req, res) => {
const { error } = validateMovie(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
let genre = await Genre.findById(req.body.genreId);
console.log(genre);
if (!genre) {
return res.status(400).send("No genre found with given id");
}
let movieDetails = await Movie.findByIdAndUpdate(
req.params.id,
{
title: req.body.title,
numberInStock: req.body.numberInStock,
dailyRentalRate: req.body.dailyRentalRate,
liked: req.body.liked,
genre: {
_id: genre.id,
name: genre.name,
},
}, //when using patch method, then u need not have to write this whole thing. instead just write req.body
{ new: true }
);
if (!movieDetails) {
return res.status(404).send("No such movie details found.");
}
res.send(movieDetails);
});
router.delete("/:id", async (req, res) => {
let movieDetails = await Movie.findByIdAndDelete(req.params.id);
if (!movieDetails) {
return res.status(404).send("No id found for given Movie");
}
res.send(movieDetails);
});
module.exports = router;

Updating a field in MondoDB

I am writing a multi-user online dictionary. I want to implement a leadership board, e.i. "score" attribute increases, as soon as a user adds a word. I have a rough idea on how to do it, and tried one solution, however it does not work. Could you please guide me?
Word API route
const express = require('express');
const router = express.Router();
const Word = require('../../models/Word');
const User = require('../../models/User');
const validateWordInput = require('../../validation/word');
const passport = require('passport');
// #route POST api/words
// #desc Add words to profile
// #access Private
router.post(
'/',
passport.authenticate('jwt', { session: false }),
(req, res) => {
const { errors, isValid } = validateWordInput(req.body);
// Check validation
if (!isValid) {
// Return any errors
return res.status(400).json(errors);
}
Word.find({}).then(word => {
if (
word.filter(
wrd =>
wrd.ugrWordCyr.toString().toLowerCase() ===
req.body.ugrWordCyr.toLowerCase()
).length !== 0
) {
return res
.status(404)
.json({ wordalreadyexists: 'Word already exists' });
} else {
const newWord = new Word({
user: req.user.id,
ugrWordCyr: req.body.ugrWordCyr,
rusTranslation: req.body.rusTranslation,
example: req.body.example,
exampleTranslation: req.body.exampleTranslation,
origin: req.body.origin,
sphere: req.body.sphere,
lexis: req.body.lexis,
grammar: req.body.grammar,
partOfSpeech: req.body.partOfSpeech,
style: req.body.style
});
newWord.save().then(word => res.json(word));
User.update(
{ _id: '5cf0cb78b3105d1ba8e30331' },
{ $inc: { score: 1 } }
);
}
});
}
);
User model
This is where a score attribute is located
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create schema
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
score: {
type: Number,
default: 0
},
avatar: {
type: String
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model('users', userSchema);
After successfully saving the word, we should update the user count
To update the respective user's score you can do the following:
newWord.save().then((word) => {
//now update user model
User.findOne({ _id: req.user.id }) <-- or an id you would like
.then((foundUser) => {
foundUser.score = foundUser.score + 1
foundUser.save()
.then((savedUser) => {
res.json({ word, savedUser })
})
.catch((err) => {
return res.status(400).json({ error: "could not add score"})
})
})
.catch((err) => {
return res.status(400).json({ error: "could not find user"})
})
})

Resources