Return only created subdocument mongoose - mongodb

I need to push a new document into an array and use his _id.
Right now im using findOneAndUpdate, i know i can use { new: true } but i only need the created document and not the parent document.
this is my code so far
User.findOneAndUpdate(
{
'posts._id': req.params.id
},
{
$push: {
'posts.$.comments': {
from: {
_id: req.user._id,
username: req.user.username,
},
body: req.body.commentBody
}
}
},
err => {
if (err) console.log(err)
// Do something with ObjectId
}
);
Thanks in advance.

findOneAndUpdate callback gives you the updated document.
You have the Post's _id. You can use that to find the post to which you are adding the comment to. As you are pushing the comment, it will be the last element in the post array.
var mypost = doc.posts.find(function(post){
return post._id.toString()==req.params.id
});
console.log(mypost.comments[mypost.comments.length]._id)

Related

How to return an aggregate query in an Apollo resolver (Meteor/Apollo/Graphql)?

I'm trying to run a query with an aggregate in Meteor and I've not been able to figure out how to return an aggregation query.
In my GraphQL schema:
type UserRelation {
date: String!
userID: String!
}
type UserData {
userID: String!
description: String!
friends_list: [UserRelation]!
}
extend type Query {
getFriends(userID: String!, friendID: String): [UserRelation]
}
In my resolvers.js:
import UserData from "./userData";
export default {
Query: {
getFriends(obj, args, context) {
if (args.friendID) return UserData.rawCollection().aggregate([
{
$match: {
_id: 'cuS7KebEQDRv2iFpJ'
}
},
{
$unwind: '$friends_list'
},
{
$match: {
'friends_list._id': '8GW4gjwWhkEexfndd'
}
}
]);
return UserData.findOne({ userID: args.userID }, {fields: {_id: 0, friends_list: 1 }}).friends_list;
}
}
}
In this hardcoded example, I have the following document in my database:
And I want to return the entire document with ONLY the user with a matched _id and whose friends_list has another user with the second matched _id. So this way I can return the entire document with only that 1 element in the friends_list array instead of all other elements as well.
Now this query works fine in Robo3T (a MongoDB GUI), but there's an issue with the return statement when I run it in Graphiql as an error is thrown which states:
"Expected Iterable, but did not find one for field \"Query.getFriends\"." When I log that statement, I see a Mongo AggregationCursor. But I'm not sure how I should "convert" this to a type that the resolver can return properly.
Any help is appreciated, thank you!
I don't know if I actually figured it out because I need to test it more, but this is working so far, in my resolvers.js I have:
import UserData from "./userData";
async function getFriend(userID, friendID) {
return UserData.rawCollection().aggregate([
{
$match: {
_id: userID
}
},
{
$unwind: '$friends_list'
},
{
$match: {
'friends_list._id': friendID
}
}
]).toArray();
}
export default {
Query: {
async getFriends(obj, args, context) {
if (args.friendID){
const result = await getFriend(args.userID, args.friendID);
return result[0].friends_list;
}
return UserData.findOne({ userID: args.userID }, {fields: {_id: 0, friends_list: 1 }}).friends_list;
}
}
}
By making it async I was able to get this done. Not sure what implications this has, but so far it works. If anyone is able to review this and give some critique to improve this it would be sincerely appreciated, as any information about this has been excruciatingly difficult to find, as I have not seen any use-cases of this so far.

Mongoose findOneAndUpdate updates the wrong item

In my model I have a thread that contains an array of comments. When I try to update these comments it always updates the wrong one and I cannot figure out why.
Thread.findOneAndUpdate({
'comments._id': req.params.commentId,
'comments.created_by.user_id': user._id
},
{
$set: {
'comments.$.content': req.body.content,
}
}, { new: true }, (err, thread) => {
if(!err && thread){
res.status(200).json({success: true})
}
})
This code works, but it always updates the first comment rather than the one I am trying to update.

mongooseJS returning an object after update?

Is it possible to return a document after updating it?
my current code looks something like this:
module.exports.updateEmail = function(id, data, callback) {
User.findByIdAndUpdate( id, {
$set: { "email": email }
}, callback);
}
how would I pull the User document and pass it back?
add {new : true} update option, to return the updated document, the callback will have the updated document you can return it
module.exports.updateEmail = function(id, data, callback) {
User.findByIdAndUpdate( id,
{$set: { "email": email }},
{new : true}, // to return updated document
callback
);
}

How to save / update multiple documents in mongoose

I am reading all documents of a specific schema from Mongoose. Now in my program I am doing some modifications to the results I got from Mongoose over time. Something like this:
var model = mongoose.model("Doc", docSchema);
model.find(function(err, result){
// for each result do some modifications
});
How can I send all the results back to the database to be saved? Currently I am iterating the documents and doing a save() on every document. I think there must be a better way. But currently I only find information on updating documents IN the database without returning them. Or bulk updates which do the SAME to update to each document.
You can use update query with multi:true which update all documents in your db.
please find below reference code,
model.update({ "_id": id }, { $set: { "Key": "Value" } }, { multi: true }, function (err, records) {
if (err || !records) {
return res.json({ status: 500, message: "Unable to update documents." });
} else {
return res.json({ status: 200, message: "success" });
}
});
If you are trying to make the same change to each document in the results, you could do something like this:
model.update({ _id: { $in: results.map(doc=>doc._id) }}, { yourField: 'new value' }, { multi: true })

MongoDb $pull by array index

I was looking to pull(remove) values from my data collection based on array index.
this is how my collection looks.
"experience" : [
"neeee",
"avvvvvvv",
],
I'm looking to remove experience[1]
var update = {
$pull: {
'profile.experience': delet
}
};
this.findByIdAndUpdate(id,update,{ 'new': true},function(err,doc) {
if (err) { console.log(err);
callback(err);
} else if(doc){
callback(null,doc);
}
my delet looks like this: [1]
i was not able to delete (pull) what may be the reason.