change bool value mongodb - node.js

m beginner at react i have a little problem i want to change a bool value which is isApproved so the admin click a button and approve the post so it can be displayed here is my code . can anyone help me
this is the function that change the value of isApproved
//#route put api/posts/approve/:id
//#desc approve post
//#access Private
router.post('/:id/approve', auth, async(req, res) => {
console.log("action base de donne begin");
Post.findById(req.params.id, (err, post) => {
console.log(post.isApproved);
if (err) {
console.log(err);
} else if (post.isApproved == false) {
post.update({$set: {isApproved: true}});
} else {
post.update({$set: {isApproved: false}});
}
});
});
the post model :
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
text: {
type: String,
required: true
},
name: {
type: String
},
avatar: {
type: String
},
isApproved: {
type: Boolean,
default: false
},
likes: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'users'
}
}
],
comments: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
text: {
type: String,
required: true
},
name: {
type: String
},
avatar: {
type: String
},
date: {
type: Date,
default: Date.now
}
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Post = mongoose.model('post', PostSchema);
approve action :
// Approve Approve
export const approve = id => async dispatch => {
try {
console.log('action is begin');
console.log(id);
const res = await axios.post(`/api/posts/${id}/approve`);
console.log('la valeur dans action est',res)
dispatch({
type: APPROVE_POST,
payload: { id, isApproved: res.data }
});
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
post reducers
import {
GET_POSTS,
POST_ERROR,
UPDATE_LIKES,
DELETE_POST,
ADD_POST,
GET_POST,
ADD_COMMENT,
REMOVE_COMMENT,
APPROVE_POST
} from '../actions/types';
const initialState = {
posts: [],
post: null,
loading: true,
error: {}
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_POSTS:
return {
...state,
posts: payload,
loading: false
};
case GET_POST:
return {
...state,
post: payload,
loading: false
};
case ADD_POST:
return {
...state,
posts: [payload, ...state.posts],
loading: false
};
case DELETE_POST:
return {
...state,
posts: state.posts.filter(post => post._id !== payload),
loading: false
};
case POST_ERROR:
return {
...state,
error: payload,
loading: false
};
case UPDATE_LIKES:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id ? { ...post, likes: payload.likes } : post
),
loading: false
};
case APPROVE_POST:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id ? { ...post, isApproved: payload.isApproved } : post
),
loading: false
};
case ADD_COMMENT:
return {
...state,
post: { ...state.post, comments: payload },
loading: false
};
case REMOVE_COMMENT:
return {
...state,
post: {
...state.post,
comments: state.post.comments.filter(
comment => comment._id !== payload
)
},
loading: false
};
default:
return state;
}
}
case APPROVE_POST:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id ? { ...post, isApproved: payload.isApproved } : post
),
loading: false
};

{ "$eq": [ false, "$isApproved" ] } will return true or false
db.collection.update(
{},
[ { "$set": { "isApproved": { "$eq": [ false, "$isApproved" ] } } } ]
);
Use findByIdAndUpdate
Demo - https://mongoplayground.net/p/4kCEaEpuIko

i change the code to this but i always have a false value
router.post('/:id/approve', auth, async(req, res) => {
console.log("action base de donne begin");
Post.findById(req.params.id, (err, post) => {
console.log(post.isApproved);
if (err) {
console.log(err);
} else if (post.isApproved == false) {
post.update(
{},
[ { "$set": { "isApproved": { "$eq": [ true, "$isApproved" ] } } } ]
);
} else {
post.update(
{},
[ { "$set": { "isApproved": { "$eq": [ false, "$isApproved" ] } } } ]
);
}
});
});

Related

to find total following and follower

export const add_followers = async (req: Request, res: Response) => {
reqInfo(req)
let user: any = req.header('user'),
body = req.body,
response: any
console.log("user", user);
try {
response = await userModel.findOne({
_id: ObjectId(body.id), isActive: true, "follow.followers": { $elemMatch: { followedBy: ObjectId(user?._id) } }
}) // body.id -> jene follow karvanu 6 // user.id je follow kare 6
console.log("response", response);
if (response) {
console.log("response cond 1")
let data = await userModel.findOneAndUpdate({ _id: ObjectId(body.id), isActive: true }, {
$pull: { "follow.followers": { followedBy: ObjectId(user._id) } }
}, { new: true })
data = await userModel.findOneAndUpdate({ _id: ObjectId(user._id), isActive: true }, {
$pull: { "follow.following": { followingBy: ObjectId(body.id) } }
}, { new: true })
return res.status(200).json(await apiResponse(200, "unFollow Successfully", data, {}));
}
if (!response) {
console.log("response cond 2")
response = await userModel.findOneAndUpdate({ _id: ObjectId(body.id), isActive: true }, {
$push: {
"follow.followers": {
followedBy: ObjectId(user?._id),
name: user?.userName,
image: user?.userImage
},
$count: "follow.followers"
},
}, { new: true })
await userModel.findOneAndUpdate({ _id: ObjectId(user._id), isActive: true }, {
$addToSet: {
"follow.following": {
followingBy: ObjectId(body.id),
name: body?.userName,
image: body?.userImage
},
$count: "follow.following"
},
}, { new: true })
return res.status(200).json(await apiResponse(200, responseMessage?.addDataSuccess("following"), response, {}));
} else {
return res.status(403).json(await apiResponse(403, responseMessage?.getDataNotFound("user"), null, {}))
}
} catch (error) {
console.log(error)
return res.status(500).json(await apiResponse(500, responseMessage?.internalServerError, {}, error))
}
}
i want to get totalfollower and following in this user can follow complete but did'nt get total number of follower

how to find in an Array of Objects by id?

I want to use mongoose to find in an array of objects by id.
I have this list:
{
"data":[
{
"_id":"60ce0ea7eb945a22288fd0ba",
"parent":"50ce0e44eb945a22288fd0b1",
"label":"label 1-2",
"ancestors":[
{
"_id":"50ce0e44eb945a22288fd0b1",
"label":"label 1-1"
},
{
"_id":"40ce077e90c6262bdc21aa44",
"label":"label 1"
}
]
},
{
"_id":"50ce0e44eb945a22288fd0b1",
"parent":"60ce077e90c6262bdc21aa55",
"label":"label 1-1",
"ancestors":[
{
"_id":"40ce077e90c6262bdc21aa44",
"label":"label 1"
}
]
},
{
"_id":"40ce077e90c6262bdc21aa44",
"parent":null,
"label":"label 1",
"ancestors":[]
}
]
}
This is the schema:
const categorySchema = new mongoose.Schema(
{
label: {
type: String,
required: true
},
parent: {
type: ObjectId,
default: null,
ref: 'category'
},
ancestors: [
{
_id: {
type: ObjectId,
ref: 'category'
},
label: String
}
]
},
{ timestamps: true }
);
I tried to do this:
async getDescendants(req, res) {
let { pId } = req.body;
if (!pId) {
return res.json({ error: 'All filled must be required' });
} else {
try {
const data = await patternModel
.find({ 'ancestors._id': pId })
.select({
_id: false,
label: true
})
.exec();
if (data) {
return res.json({ data });
}
} catch (err) {
return res.json({ err: err });
}
}
}
this is my actual result:
{
"data": []
}
when I change .find({ 'ancestors._id': pId }) to .find({ 'ancestors.label': label }) it works but not for the id.
It is not a simple field. It is an array of subdocuments. Use elemMatch.
Edit: When querying _id fields you will have to wrap convert them into ObjectIds (specific to Mongo).
let newPid = mongoose.Types.ObjectId(pId);
const data = await patternModel.find({ ancestors: { $elemMatch : { _id: newPid} } })
.select({ _id: false,label: true })
.exec();

I want to pass array object inside array subdocument in mongoose

Here is my Schema
I am trying to add replies array inside answers array. If someone answers a question and if someone wants to reply on the given answer
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const questionSchema = new mongoose.Schema(
{
postedBy: {
type: ObjectId,
required: true,
ref: "User",
},
question: {
type: String,
required: true,
},
photo: {
data: String,
required: false,
},
answers: [
{
userId: { type: ObjectId, ref: "User" },
answerType: {
data: String,
required: false,
},
answer: String,
replies: [
{
userId: { type: ObjectId, ref: "User" },
reply: String,
replyType: {
data: String,
required: false,
},
},
],
},
],
questionType: {
data: String,
required: false,
},
createdAt: {
type: Date,
required: true,
default: Date.now,
},
},
{ timeStamps: true }
);
module.exports = mongoose.model("Question", questionSchema);
Here is my Controller method
exports.postReply = (req, res) => {
const reply = req.body.reply || "";
const userId = req.user._id || "";
const answerId = req.body.answerId || "";
Question.findByIdAndUpdate(
{ _id: answerId },
({ $push: { answers: { answer: { replies: { reply, userId } } } } },
{ new: true }),
(err, newReply) => {
if (err) {
res.status(400).json({
error: errorHandler(err),
});
} else {
res.json({
msg: "Reply posted successfully",
newReply,
});
}
}
);
};
I feel I am going wrong on the findOneAndUpdate method. I am getting no error on the console but newReply comes null. Any help will be appreciated.
I would suggest you using the $addToSet instead of the $push operator as you are adding a document to the array. (see: https://docs.mongodb.com/manual/reference/operator/update/addToSet/).
If you want to add more than one document to the array, refer also to the $each operator together with $addToSet.
So your coding can look similiar to this (note: the variable 'yourDocument' is the document you want to add):
Question.findByIdAndUpdate(
{ _id: answerId },
{ $addToSet: { answers: yourDocument } },
{ new: true },
(err, newReply) => {
if (err) {
res.status(400).json({
error: errorHandler(err),
});
} else {
res.json({
msg: "Reply posted successfully",
newReply,
});
}
}
);
};
The problem is clearly the parentesis around
({ $push: { answers: { answer: { replies: { reply, userId } } } } }, { new: true })
Doing this console.log( ({a:1}, {b:2}) ); will log {b: 2} which means you are doing this
Question.findByIdAndUpdate( { _id: answerId }, { new: true }, (err, newReply) => {
So remove the parentesis and you should be good
Question.findByIdAndUpdate(
{ _id: answerId },
{ $push: { answers: { answer: { replies: { reply, userId } } } } },
{ new: true },
(err, newReply) => {
if (err) {
res.status(400).json({
error: errorHandler(err),
});
} else {
res.json({
msg: "Reply posted successfully",
newReply,
});
}
}
);

Cast to ObjectId failed for value at path for model error

This is my Profile Schema:
const mongoose = require('mongoose');
const ProfileSchema = new mongoose.Schema({
user: {
// Special field type because
// it will be associated to different user
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
company: {
type: String,
},
website: {
type: String,
},
location: {
type: String,
},
status: {
type: String,
required: true,
},
skills: {
type: [String],
required: true,
},
bio: {
type: String,
},
githubusername: {
type: String,
},
experience: [
{
title: {
type: String,
required: true,
},
company: {
type: String,
required: true,
},
location: {
type: String,
},
from: {
type: Date,
required: true,
},
to: {
type: Date,
},
current: {
type: Boolean,
default: false,
},
description: {
type: String,
},
},
],
education: [
{
school: {
type: String,
required: true,
},
degree: {
type: String,
required: true,
},
fieldofstudy: {
type: String,
required: true,
},
from: {
type: Date,
required: true,
},
to: {
type: Date,
},
current: {
type: Boolean,
default: false,
},
description: {
type: String,
},
},
],
social: {
youtube: {
type: String,
},
twitter: {
type: String,
},
facebook: {
type: String,
},
linkedin: {
type: String,
},
instagram: {
type: String,
},
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = Profile = mongoose.model('profile', ProfileSchema);
This is my view api. It doesn't work. it only return Cast to ObjectId failed for value { 'experience._id': '5edcb6933c0bb75b3c90a263' } at path _id for model profile
router.get('/experience/viewing/:viewexp_id', auth, async (req, res) => {
try {
const exp = await Profile.findById({
'experience._id': req.params.viewexp_id,
});
if (!exp) {
return res.status(404).json({ msg: 'Experience not found' });
}
res.json(exp);
} catch (err) {
console.error(err.message);
res.status(500).send(err.message);
}
});
How can I fix this? I tried looking at the stackoverflow of the same errors. still it doesn't seem to work.
and this is what I am trying to hit
The problem is that you have to convert your string _id to mongoose object id using this function mongoose.Types.ObjectId and my suggestion is to use findOne function instead of findById,
var mongoose = require('mongoose');
router.get('/experience/viewing/:viewexp_id', auth, async (req, res) => {
try {
let id = mongoose.Types.ObjectId(req.params.viewexp_id);
const exp = await Profile.findOne(
{ "experience._id": req.params.viewexp_id },
// This will show your sub record only and exclude parent _id
{ "experience.$": 1, "_id": 0 }
);
if (!exp) {
return res.status(404).json({ msg: 'Experience not found' });
}
res.json(exp);
} catch (err) {
console.error(err.message);
res.status(500).send(err.message);
}
});
var mongoose = require('mongoose');
router.get('/experience/viewing/:viewexp_id', auth, async (req, res) => {
try {
const exp = await Profile.findOne({
'experience._id': mongoose.Types.ObjectId(req.params.viewexp_id),
});
if (!exp) {
return res.status(404).json({ msg: 'Experience not found' });
}
res.json(exp);
} catch (err) {
console.error(err.message);
res.status(500).send(err.message);
}
});
You are saving object id . but your param id is string. convert it in ObjectId. Please check my solution.
router.post(
"/",
[
auth,
[
check("status", "status is required").not().isEmpty(),
check("skills", "skills is required").not().isEmpty(),
],
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
company,
website,
location,
bio,
status,
githubuername,
skills,
youtube,
facebook,
twitter,
instagram,
linkedin,
} = req.body;
const profileFileds = {};
profileFileds.user = req.user.id;
if (company) profileFileds.company = company;
if (website) profileFileds.website = website;
if (location) profileFileds.location = location;
if (bio) profileFileds.bio = bio;
if (status) profileFileds.status = status;
if (githubuername) profileFileds.githubuername = githubuername;
if (skills) {
profileFileds.skills = skills.split(",").map((skill) => skill.trim());
}
//Build profile object
profileFileds.social = {};
if (youtube) profileFileds.social.youtube = youtube;
if (twitter) profileFileds.social.twitter = twitter;
if (facebook) profileFileds.social.facebook = facebook;
if (linkedin) profileFileds.social.linkedin = linkedin;
if (instagram) profileFileds.social.instagram = instagram;
try {
let profile = await Profile.findOne({ user: req.user.id });
if (profile) {
//update
profile = await Profile.findOneAndUpdate(
{ user: req.user.id },
{ $set: profileFileds },
{ new: true }
);
return res.json(profile);
}
//Create profile
profile = new Profile(profileFileds);
await profile.save();
res.json(profile);
} catch (err) {
console.error(err.message);
res.status(500).send("server Error");
}
}
);

MongoDB find overlapping date range on sub-documents

Supposing I have this data:
[{
"name": "New Training1",
"participants": ["5d2eca379b0d361b18d2f3d0", "5d31290c21729014a0bdd0ba"],
"schedule": [{
"start": "2019-10-07T12:00:00.000Z",
"end": "2019-10-07T14:00:00.000Z"
}]
}, {
"name": "New Training2",
"participants": ["5d2eca379b0d361b18d2f3d0"],
"schedule": [{
"start": "2019-10-07T14:00:00.000Z",
"end": "2019-10-07T15:00:00.000Z"
}]
}, {
"name": "New Training3",
"participants": ["5d31290c21729014a0bdd0ba"],
"schedule": [{
"start": "2019-10-07T14:00:00.000Z",
"end": "2019-10-07T16:00:00.000Z"
}]
}]
What I want to do is when I attempt to add the participant with the id of 5d2eca379b0d361b18d2f3d0 to the training New Training3, the app will throw an error indicating that there was a conflict on the schedule and will return the conflicting schedule. Based on the data above the system must return this training as it has a conflicting schedule:
{
"name": "New Training2",
"participants": ["5d2eca379b0d361b18d2f3d0"],
"schedule": [{
"start": "2019-10-07T14:00:00.000Z",
"end": "2019-10-07T15:00:00.000Z"
}
}
This is what I have so far.
Training model:
const mongoose = require('mongoose');
const ScheduleSchema = require('../models/schedule.model').schema;
const TrainingSchema = new mongoose.Schema(
{
name: {
type: String,
unique: true,
required: true
},
participants: [{ type: mongoose.Schema.ObjectId, ref: 'Participant' }],
schedule: [ScheduleSchema]
},
{
versionKey: false,
timestamps: true
}
);
module.exports = mongoose.model('Training', TrainingSchema);
Partcipant model:
const mongoose = require('mongoose');
const ParticipantSchema = new mongoose.Schema(
{
name: {
type: String,
required: true
}
}
);
Schedule model
const mongoose = require('mongoose');
const ScheduleSchema = new mongoose.Schema(
{
start: {
type: Date,
required: true
},
end: {
type: Date,
required: true
}
},
{
versionKey: false,
timestamps: false
}
);
module.exports = mongoose.model('Schedule', ScheduleSchema);
Function to get trainings with overlapping schedules if I add a praticpant using participantId to a training with the given trainingId:
const model = require('../models/training.model');
exports.participantScheduleOverlaps = async (trainingId, participantId) => {
return new Promise((resolve, reject) => {
model.find(
);
});
};
I need help building a MongoDB query to find the overlapping schedule. Thanks.
Try this one.
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const util = require("util")
mongoose.connect("mongodb://localhost/mongoose-doc", { useNewUrlParser: true })
const ScheduleSchema = new Schema(
{
start: {
type: Date,
required: true
},
end: {
type: Date,
required: true
}
},
{
versionKey: false,
timestamps: false
}
);
const TrainingSchema = new Schema(
{
name: {
type: String,
unique: true,
required: true
},
participants: [{ type: mongoose.Schema.ObjectId, ref: 'Participant' }],
schedule: [ScheduleSchema]
},
{
versionKey: false,
timestamps: true
}
);
const TrainingModel = mongoose.model("Training", TrainingSchema);
const ParticipantSchema = new Schema(
{
name: {
type: String,
required: true
}
}
);
const ParticipantModel = mongoose.model("Participant", ParticipantSchema)
async function participantScheduleOverlaps(trainingId, participantId) {
try {
const trainingWeFound = await TrainingModel.aggregate([
{
$match:{
_id: mongoose.Types.ObjectId(trainingId)
}
},
{
$unwind: "$schedule"
}
]).exec()
const otherTrainingModules = await TrainingModel.aggregate(
[
{
$match:{
$and:[
{
_id:{
$ne: mongoose.Types.ObjectId(trainingId)
}
},
{
participants: {
$in: [mongoose.Types.ObjectId(participantId)]
}
}
]
}
},
{
$unwind: "$schedule"
}
]
).exec()
const overlapping = otherTrainingModules.filter((otherelem) => {
return trainingWeFound.filter(foundelem => {
(
Date.parse(otherelem.start) < Date.parse(foundelem.start)
&&
Date.parse(foundelem.start) < Date.parse(otherelem.end)
) || (
Date.parse(otherelem.start) < Date.parse(foundelem.end)
&&
Date.parse(foundelem.end) < Date.parse(otherelem.end)
)
})
})
console.log("overlapping", overlapping)
} catch(error){
console.log(error)
}
}
participantScheduleOverlaps("5d395604eb41824b5feb9c84", "5d31290c21729014a0bdd0ba")
This is my solution for anyone who might have the same or related problem:
exports.participantScheduleOverlaps = async (trainingId, participantId) => {
return new Promise((resolve, reject) => {
model.findById(trainingId, (error, item) => {
const result = {
overlap: false,
ranges: []
};
if (error) {
reject(utils.buildErrObject(422, error.message));
}
if (item) {
for (const schedule of item.schedule) {
model.find(
{
_id: { $ne: trainingId },
participants: { $eq: participantId },
'schedule.end': { $gt: schedule.start },
'schedule.start': { $lt: schedule.end }
},
(err, items) => {
if (err) {
reject(utils.buildErrObject(422, err.message));
}
if (items.length > 0) {
result.overlap = true;
result.ranges.push(
...items.map(data => {
return data.schedule;
})
);
}
resolve(result);
}
);
}
} else {
resolve(result);
}
});
});
};

Resources