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.'
});
}
}
);
Related
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;
I am trying to create a followers/following function in my project. However I cannot seem to update the DB correctly. I'm able to send the ids as they both print when I console.log but nothing in my DB updates and I do not get any response in my frontend.
route
app.put('/api/follow', async function (req, res, next){
const { id } = req.query;
const userFrom = req.body.data
console.log('OTHER USER ID',id)
console.log('CURRENT ID', userFrom)
User.findByIdAndUpdate(id), {
$push:{followers:req.body.data}
},{new:true},
(err,result)=>{
if(err) {
if(err) return res.status(400).send(err)
}
User.findByIdAndUpdate(req.body.data), {
$push:{following:id}
},{new:true}.then(result=> {
res.json(result)
}).catch(err=>{
return res.status(422).json({error:err})
})
}
})
user model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
phoneNo: String,
bio: String,
filePath: String,
following: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
followers: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
})
);
module.exports = User;
my route end function
const clickHandler = () => {
const currentID = currentUser.id;
const id = this.props.id;
console.log('CURRENT ID',currentID)
console.log('otherUserID',id)
Axios.put(`http://localhost:8080/api/follow/?id=${id}`, { data: currentID }, { headers: authHeader() })
.then(response => {
if (response.data.success) {
console.log('FOLLOWED', response.data)
// this.setState({ userDetails: response.data.details })
} else {
alert('Error')
}
})
}
This should be
User.findByIdAndUpdate(id, {
You should not close the bracket after id but after new: true})
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}
I am trying to delete two record from different database (practice log, student) within the same session, the problem is the practice log record is found successfully and shown in console.log(deletePracticeLog), but it cannot be remove from the database. anyone know what have I done wrong? I am very confused.
const deleteStudentById = async (req, res, next) => {
const sid = req.params.sid;
let deleteStudent;
let deletePracticeLog;
try {
deleteStudent = await Students.findById(sid).populate("teacher");
} catch (err) {
const error = new HttpError("Delete failed, please try again.", 500);
return next(error);
}
try {
deletePracticeLog = await PracticeLog.find({ student: sid }).exec();
console.log(deletePracticeLog); // **<-this correctly show the record needed to be deleted, it's a object within an array**
} catch (err) {
const error = new HttpError("Cannot delete, please try again.", 500);
return next(error);
}
if (!deleteStudent) {
const error = new HttpError("Could not find student for this id.", 404);
return next(error);
}
try {
const sess = await mongoose.startSession();
sess.startTransaction();
await deleteStudent.remove({ session: sess }); //delete the student from student database
deleteStudent.teacher.students.pull(deleteStudent); //delete the student id from teacher database
await deleteStudent.teacher.save({ session: sess });
await deletePracticeLog.remove({ session: sess }); // **<-this line caused error, when this line is removed, other code run successfully and other record are deleted.**
await sess.commitTransaction();
} catch (err) {
const error = new HttpError("Cannot delete student with provided id.", 500);
return next(error);
}
res.status(200).json({ message: "Deleted student." });
};
when you are using await, you don't need to exec()
delete your exec() from
deletePracticeLog = await PracticeLog.find({ student: sid }).exec();
change to
deletePracticeLog = await PracticeLog.find({ student: sid })
beacuse you use exec(), use this code for remove data
await deletePracticeLog[0].remove({ session: sess })
if the result of PracticeLog.find({ student: sid }) is one Array and you want to delete all of them, you have to use deleteMany like this:
PracticeLog.deleteMany({ student: sid }).session(sess)
it's worked for me
here is the Mongoose schema:
const mongoose = require("mongoose");
const studentsSchema = new mongoose.Schema({
name: { type: String, require: true },
email: { type: String, require: true },
contact: { type: String, require: true },
teacher: { type: mongoose.Types.ObjectId, require: true, ref: "teachers" },
practiceLogs: [
{ type: mongoose.Types.ObjectId, require: true, ref: "practice_logs" },
],
});
module.exports = mongoose.model("students", studentsSchema);
const practiceLogSchema = new mongoose.Schema({
repertoire: { type: String, require: true },
student: { type: mongoose.Types.ObjectId, require: true, ref: "students" },
teacher: { type: mongoose.Types.ObjectId, require: true, ref: "teachers" },
});
module.exports = mongoose.model("practice_logs", practiceLogSchema);
here is the mongoose.connect():
const url =
"myURL";
mongoose
.connect(url, { useUnifiedTopology: true, useNewUrlParser: true })
.then(() => {
app.listen(5000);
console.log("connected.");
})
.catch((err) => {
console.log(err);
});
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"})
})
})