I need to push data in nested subdocument array(replyComment):
This is an example of a document from my database:
{
comments: [
{
replyComment: [],
_id: 601a673735644c83e0aa1be3,
username: 'xyz123#gmail.com',
email: 'xyz213#gmail.com',
comment: 'test123'
},
{
replyComment: [],
_id: 601a6c94d1653c618c75ceae,
username: 'xyz123#gmail.com',
email: 'xyz123#gmail.com',
comment: 'reply test'
}
],
_id: 601a3b8038b13e70405cf9ea,
title: 'latest test',
snippet: 'latest test snippet',
body: 'latest test body',
createdAt: 2021-02-03T05:58:24.123Z,
updatedAt: 2021-02-03T12:28:33.237Z,
__v: 7
}
I am also mentioning my code snippet:
app.post('/:id/replyComment',(req,res) => {
const replyComm = new Comment(req.body);
Topic.findById(req.params.id)
.then((result) => {
topic = result,
console.log(topic);
topic.update({_id:req.params.id, "comments._id": req.body.comment_id},
{ $push: {"comments.$.replyComment": {replyComment: replyComm}}}
)
topic.save()
.then((result) => {
// console.log(result);
res.send({
text: "Replied",
})
})
.catch((err) => {
console.log(err);
});
})
});
By running the request I am not getting any error but still the same documented is getting printed on my terminal and there is no change in "replyComment" subarray.
Pls suggest how to make this work or any alternate method.
I prefer to use objects instead of arrays by converting objects to the array Object.keys(data.comments)
{
comments:
{
'601a673735644c83e0aa1be3':{
username: 'samyakjain971#gmail.com',
email: 'samyakjain971#gmail.com',
comment: 'test123'
}
},
{
'601a6c94d1653c618c75ceae':{
username: 'samyakjain971#gmail.com',
email: 'samyakjain971#gmail.com',
comment: 'reply test'
}
},
_id: 601a3b8038b13e70405cf9ea,
title: 'latest test',
snippet: 'latest test snippet',
body: 'latest test body',
createdAt: 2021-02-03T05:58:24.123Z,
updatedAt: 2021-02-03T12:28:33.237Z,
__v: 7
}
define topic variable like this :
let topic = result;
console.log(topic);
topic.update({_id:req.params.id, "comments._id": req.body.comment_id},
{ $push: {"comments.$.replyComment": {replyComment: replyComm}}}
)
Related
I have an express controller that creates a new Post document like this
exports.createPost = async (req, res, next) => {
try {
const user = await User.findOne({ _id: req.uid });
if (!user) throw new ServerError(
"user with provided authorid doesn't exist",
400
);
const newPost = new Post({
author: req.uid,
title: req.body.title,
caption: req.body.caption,
media: req.body.media,
location: req.body.location
});
const createdPost = await newPost.save();
res.status(201).send(createdPost);
} catch (error) {
next(error);
}
};
When tested with postman it works as intended and the _id field shows no problems
{
author: "LJFlAgRjqXQ1K7HUSyj12EmxxXD2",
title: "title",
caption: "caption",
comments: [],
media: [],
likes: [],
location: { coordinates: [] },
_id: "61af0c16423073390394717d", // _id as expected
date: "2021-12-07T07:24:06.809Z",
__v: 0
}
But when testing the same controller with Jest and mongodb-memory-server, the _id field turns to be a call to the ObjectId construtor instead of being a new id
{
author: "61af0c43870651bbd1a7a81d",
title: "title",
caption: "caption",
comments: [],
media: [],
likes: [],
location: { coordinates: [] },
_id: new ObjectId("61af0c43870651bbd1a7a820"), // _id is a constructor call
date: "2021-12-07T07:24:51.653Z",
__v: 0
}
is this an issue with mongodb-memory-server? how would I get the correct id of the post to use it in a test?
I basically wrote a code to check if the data is existing or not in the mongoDB and if it is then I'm trying to create a new document and if it is then I'm basically updating the same document
this is my controller code
Controller.js
try {
console.log(req.body)
let data = await IITSchema.findOne({ Email })
console.log(data)
if (data) {
const updateFormData = await IITSchema.findOneAndUpdate(
{ Email },
{
PhoneNumber,
YearofGrad: YearofGrad,
FullName,
Evidence,
CollegeName: CollegeName,
user: SaveUserData._id,
City: City,
GraduationDegree: GraduationDegree,
Department: Department,
placement_time: placement_time,
targeted_companies: targeted_companies,
interests,
In_what_areas_do_you_need_our_help,
Others,
}
);
return res.status(200).json({ message: "update", data: updateFormData });
} else {
// if (!SaveFormData) {
const newformdata = new IITSchema({
})
const newFormData = await IITSchema.create({
Email,
password: hashedPassword,
PhoneNumber,
YearofGrad: YearofGrad,
FullName,
Evidence,
CollegeName: CollegeName,
// user: user._id,
City: City,
GraduationDegree: GraduationDegree,
Department: Department,
placement_time: placement_time,
targeted_companies: targeted_companies,
interests,
In_what_areas_do_you_need_our_help,
Others,
});
return res.status(200).json({ message: "create", data: newFormData });
}
} catch {
(err) => {
console.log("error from New Step Form", err);
res.json({ error: err });
};
}
this is my Model
const mongoose = require("mongoose");
const IITSchema = new mongoose.Schema({
FullName: String,
Email: String,
interests: { type: [String] },
CollegeName: String,
YearofGrad: String,
password: String,
Evidence: Boolean,
Department: String,
GraduationDegree: String,
In_what_areas_do_you_need_our_help: { type: [String] },
City: String,
placement_time: String,
targeted_companies: String,
PhoneNumber: String,
Others: String,
referral: { type: String, default: null },
});
module.exports = mongoose.model("iitbombay", IITSchema);
and this is the req.body that I'm getting from the front end
{
FullName: 'Mohammed Khan',
Email: 'aven.farhan#gmail.com',
password: 'asdfsadfsd',
Evidence: true,
PhoneNumber: '+919515876470',
CollegeName: ' GURU PRAKASH B.ED. COLLEGE , Kaimur (Bhabua), Bihar',
YearofGrad: 2023,
GraduationDegree: 'Bsc',
Department: 'CSE',
City: 'Adoni',
In_what_areas_do_you_need_our_help: [ 'Complete Placement Preparation' ],
targeted_companies: 'FAANG (Facebook, Amazon, Apple, Netflix and Google)',
placement_time: 'Less than 1 month',
interests: [ 'Data Science / Analytics' ]
}
this is the code that I'm using to send the data to the backend i.e node js and mongodb
await fetch(BASE_URL + "/iitbfform", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newData),
})
.then((res) => res.json())
.then((data) => {
console.log("Response from firstForm", data);
});
the code is completely fine but the document is not getting saved
it would mean alot if some can point out the error that I'm doing over here
I am trying to update a users role using mongoose . I have been using mongoose findOneAndUpdate but have not been able to update the role. I dont get any error messages but i get the doc before the update. So i did some research and tried to add {new:true} but it did not change anything. Then I saw someone use the aggregate query $push but that did not either work.
I have rewritten this query many times without giving me the expected results
exports.changeRole = async (req, res) => {
User.findOneAndUpdate(
{ id: req.param.userId },
{
$push: {
$set: { "roles[0].name": req.body.name },
},
},
{ new: true }
)
.populate("roles", "-__v")
.exec((err, data) => {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
};
How I send in postman
{
"roles": ["Admin"]
}
This is what i get in my console:
{
roles: [ { _id: 606242fa3bcbc13305bee567, name: 'user' } ],
_id: 606307a839a54f7982f8ff84,
username: 'before',
email: 'before#gmail.com',
password: '$2a$/lvMv80IPZe9FSm',
__v: 1
}
I have one model that is called User
const userSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
min: 6,
max: 255,
},
email: {
type: String,
required: true,
min: 6,
max: 255,
},
password: {
type: String,
required: true,
min: 6,
max: 15,
},
roles: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Role",
},
],
},
{ timestamp: true }
);
This User model is referencing to Role.js. An array of objectId:s. So automatically I have four role documents created if they dont exist. Every user is referencing to one of those documents(roles)
const Role = mongoose.model(
"Role",
new mongoose.Schema({
name: String,
})
);
I was not thinking it right. I did not need to change my populated documents only needed to change the objectId it was referencing to in my roles:[] in User.js. Use $set to change a field and $push to to add new value.
exports.changeRole = async (req, res) => {
await User.findOneAndUpdate(
{ id: req.params.userId },
{
$set: { roles: req.body.roles },
},
{ new: true }
)
.populate("roles")
.then((data) => {
if (!data) return res.status(404).send("Not found");
res.send(data);
})
.catch((err) => {
return res.status(500).send({ message: err.message });
});
};
I am creating something like fb, I want to implement comment create functionality which I did successfully, Now I want to return newly added comment only with _id field so that I can update frontend accordingly... Can you help me Please
My schema is:
const postSchema = new Schema({
userId: { type: Types.ObjectId, ref: 'users', required: true },
content: { type: String, required: true, set: function (value) { return value.trim() } },
createdAt: { type: Date, default: Date.now() },
likes: {
totalLikes: { type: Number, default: 0, min: 0 },
usersLikedPost: [{ type: Types.ObjectId, ref: 'users', default: []}]
},
comments: [{
userId: { type: Types.ObjectId, ref: 'users', required: true },
comment: { type: String, required: true }
}]
});
module.exports = model('textPosts', postSchema);
Controller for adding new Comment is here:
exports.comment = async (req, res, next) => {
const { id, comment } = req.body;
let post = await TextPost.findById(Types.ObjectId(id));
if (!post)
return res.status(404).end();
post.comments.push({ userId: req.userId, comment });
await post.save();
post = await TextPost.populate(post,
{ path: 'comments.userId', select: 'username _id' }); // returns complete post with all comments and some other data
return res.status(201).json({ msg: 'return here newly created comment only' });
}
Use aggregate pipeline arrayElemAt, below query will return the last element of array
db.TextPost.aggregate(
{
$project: {
last: {
$arrayElemAt: [
"$comments",
-1
]
}
}
}
)
You can use $slice
Latest 5
db.posts.find( {}, { comments: { $slice: -5 } } )
First 5
db.posts.find( {}, { comments: { $slice: 5 } } )
From to
db.posts.find( {}, { comments: { $slice: [ 20, 10 ] } } )
Please check the below link
https://docs.mongodb.com/manual/reference/operator/projection/slice/
I have a mongoose query that should fetch all Participants in certain Event model, but I only get back one participant. I tried the $all method, still no result.
query:
Participants.find({'_id': {$all: event.participants}}, (err, participants) => {
if (err) {
return console.log(err);
}
console.log(participants);
});
output:
[ { createdAt: 1970-01-01T00:00:00.011Z,
_id: 5be7fc340016817bcb4ybdfc,
name: 'TEST',
ticket: 5be7fc340016817bc44fbdfb,
email: 'test#test.com',
__v: 0 } ]
expected output
[ { createdAt: 1970-01-01T00:00:00.011Z,
_id: 5be7fc340016817bcb4fbdfc,
name: 'TEST',
ticket: 5be7fc3400d16817bcb4fbdfb,
email: 'rene370d#gmail.com',
__v: 0 },
{ createdAt: 1970-01-01T00:00:00.011Z,
_id: 5be7fc340016817bcb4fbdfc,
name: 'Another test',
ticket: 5be7fc3s40016817bcb4fbdfb,
email: 'another#emai.com',
__v: 0 } ]
event.participants
participants:{
type: [mongoose.Schema.Types.ObjectId],
ref: 'ParticipantSchema'
}
From the documentation:
The $all operator selects the documents where the value of a field is an array that contains all the specified elements.
So it doesn't make much sense to use it to get all documents for a certain model.
Instead, use the $in operator
Participants.find({ _id: { $in: event.participants } }, (err, participants) => {
if (err) {
return console.log(err);
}
console.log(participants);
});