Remove element from array that is inside of another array in mongoose - node.js

The problem is that i can't remove an attachment from an object, in mongoose, with the next schema.
var question=mongoose.Schema({
_id:mongoose.Schema.Types.ObjectId
answers:[{
_id:mongoose.Schema.Types.ObjectId
attachments:[
_id:mongoose.Schema.Types.ObjectId
]
}]
});
I try to remove an attachment from a document with the next code.
Question.update({
_id: req.params.idQuestion,
'answers._id': req.params.idAnswer
}, {
$pull: {
'answers.$.attachments':{_id:req.params.idAttachment}
}
}, function (err, updated) {
if(err){
return res.status(400).send(err);
}
else if(!updated.nModified){
return res.status(400).send('Question hasn\t been updated.');
}
res.send(200);
});
I thought my query weren't correct and tried to do that in mongo shell. It worked perfectly.
db.questions.update({
_id:ObjectId('xx'),
'answers._id':ObjectId('yy')
},{
$pull:{
'answers.$.attachments':{_id:ObjectId('zz')}
}
})
Someone can help me with this problem?

Try this:
var qid=req.params.idQuestion,
aid=req.params.idAnswer;
//find
Question.find({
_id: qid,
'answers._id': aid
},{
answers:1
},function(err,question){
//change
var answers=question.answers.filter(function(el){
return el._id!=aid;
});
//update
Question.update({
_id: qid,
},{$set:{
answers:answers
}},function(err,updated){
...//your callback here
});
});

Related

Mongoose find query gives results in wrong order

I am saving an updated array of _id's to an array on a document. If I check the document, everything is updating quite nicely, but when I populate right afterward using a new find query, it doesn't work right. populate wasn't working for me, so I decided to handle it manually and I am successful at filling them in, but they're in the wrong order.
export function sort_update(req, res) {
Action.findOneAndUpdate({
_id: req.query.action
}, {
child_actions: req.body.newArray
}, {
useFindAndModify: false, new: true
}, function(err, doc) {
if (err) return res.send(500, {
error: err
});
console.log("child action id strings after update", doc.child_actions); // ["1", "2"] correct!
Action.find({'_id': {$in: doc.child_actions }}, function(err, child_action_docs) {
if (err) return res.send(500, {
error: err
});
console.log("child action objects after fill", child_action_docs); // [{ _id: "2" }, { _id: "1" }] wrong!
doc.child_actions = child_action_docs;
res.send(doc);
});
});
}
Why are they in the wrong order? Does {'_id': {$in: doc.child_actions }} simply not guarantee any order at all? Do I have to re-sort my objects to the doc.child_actions order deliberately or is there a simpler way of telling mongodb to keep the order in the original array?

How to access mongoose data : Nodejs

I am getting data like this:
This is the code :
User.find({ Username: user }, function(err, found_user) {
console.log('user data'+ found_user );
if(found_user.length > 0){
console.log('inside found user');
var recordings = found_user.recordings;
console.log(recordings)
for (var singleRecords in recordings){
console.log("Single record :"+singleRecords);
if(!singleRecords.isPlayed){
console.log(singleRecords.playingUrl);
twiml.play(singleRecords.playingUrl);
found_user.recordings[singleRecords].isPlayed = true;
found_user.save(function (err) {
if(err)
throw err
});
}
}
}
And this is the value of found User :
user data { Username: 'B',
__v: 2,
_id: 58ac15e4b4e1232f6f118ba3,
recordings:
[ { isPlayed: false,
playingUrl: 'http://localhost:8000/public/toplay/playing_file_1487672817599.mp3' },
{ isPlayed: false,
playingUrl: 'http://localhost:8000/public/toplay/playing_file_1487672827411.mp3' } ]
}
inside found user
in variable found_user. But it is not giving me any data inside it. Like found_user.Username gives undefined value.
I want to store that recordings array inside a variable. Any idea how to do it ?
find() returns an array of docs that match the criteria in the callback hence the line
var recordings = found_user.recordings;
will not work as it's expecting a Document not an array.
You could use findOne() method which returns a document as:
User.findOne({ Username: user }.exec(function(err, found_user) {
console.log('user data'+ found_user );
if (found_user) {
console.log('inside found user');
var recordings = found_user.recordings;
console.log(recordings);
}
});

Selecting only modified subdocument from Mongo

I have a mongoose query like this:
var query = Events.findOneAndUpdate({ '_id': event._id,'participants._id':participant._id},{'$set': {'participants.$': participant}}, {upsert:false,new: true},function(err,result){
if(err){
return res.status(500).jsonp({
error: 'Unable to update participant'
});
}
console.log(result.participants[0]);
res.jsonp(result.participants[0]);
});
and the query works properly modifying the participants subdocument inside Events collection.
The problem:
I need only the modified participant to be returned as JSON and I am not in need of the entire participants array but I am not able to achieve this since I get all the participants when I do console.log(result.participants);
How do I get only the modified subdocument after the query?
You may have to use the native JS filter() method as in the following:
Events.findOneAndUpdate(
{ '_id': event._id, 'participants._id': participant._id },
{ '$set': { 'participants.$': participant } },
{ upsert: false, new: true },
function(err, result){
if(err){
return res.status(500).jsonp({
error: 'Unable to update participant'
});
}
var modified = result.participants.filter(function(p){
return p._id === participant._id
})[0];
console.log(modified);
res.jsonp(modified);
}
);

Mongoose findByIdAndUpdate not returning correct model

I have an issue I've not seen before with the Mongoose findByIdAndUpdate not returning the correct model in the callback.
Here's the code:
var id = args._id;
var updateObj = {updatedDate: Date.now()};
_.extend(updateObj, args);
Model.findByIdAndUpdate(id, updateObj, function(err, model) {
if (err) {
logger.error(modelString +':edit' + modelString +' - ' + err.message);
self.emit('item:failure', 'Failed to edit ' + modelString);
return;
}
self.emit('item:success', model);
});
The original document in the db looks like this:
{
_id: 1234
descriptors: Array[2],
name: 'Test Name 1'
}
The updateObj going in looks like this:
{
_id: 1234
descriptors: Array[2],
name: 'Test Name 2'
}
The model returned from the callback is identical to the original model, not the updatedObj.
If I query the db, it has been updated correctly. It's just not being returned from the database.
This feels like a 'stupid-user' error, but I can't see it. Any ideas greatly appreciated.
In Mongoose 4.0, the default value for the new option of findByIdAndUpdate (and findOneAndUpdate) has changed to false, which means returning the old doc (see #2262 of the release notes). So you need to explicitly set the option to true to get the new version of the doc, after the update is applied:
Model.findByIdAndUpdate(id, updateObj, {new: true}, function(err, model) {...
app.put("/vendor/:id",async (req,res)=>{
res.send(req.params)
await ModelName.findByIdAndUpdate(id, {type: change}, function(err, docs){
if(err){
conslole.log(err)
}else{
console.log(docs)
}
})
})
Example:
app.put("/vendor/:id",async (req,res)=>{
res.send(req.params)
const data = await userModel.findByIdAndUpdate(req.params.id, {isVendor: true},
function(err, docs){
if(err){
conslole.log(err)
}else{
console.log(docs)
}
})
})

mongoose. updating embedded document in array

In the a official mongoose site I've found how can I remove embedded document by _id in array:
post.comments.id(my_id).remove();
post.save(function (err) {
// embedded comment with id `my_id` removed!
});
I'm interested how can I update instead removing this one?
It shoud look something like this:
YOURSCHEMA.update(
{ _id: "DocumentObjectid" , "ArrayName.id":"ArrayElementId" },
{ $set:{ "ArrayName.$.TheParameter":"newValue" } },
{ upsert: true },
function(err){
}
);
In this exemple I'm searching an element with an id parameter, but it could be the actual _id parameter of type objectId.
Also see: MongooseJS Doc - Updating Set and Similar SO question
You could do
var comment = post.comments.id(my_id);
comment.author = 'Bruce Wayne';
post.save(function (err) {
// emmbeded comment with author updated
});
Update to latest docs on dealing with sub documents in Mongoose. http://mongoosejs.com/docs/subdocs.html
var Parent = mongoose.model('Parent');
var parent = new Parent;
// create a comment
parent.children.push({ name: 'Liesl' });
var subdoc = parent.children[0];
console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
subdoc.isNew; // true
parent.save(function (err) {
if (err) return handleError(err)
console.log('Success!');
});

Resources