Reputation: 3545
I work with nodejs/express/mongoose/angularjs. I'd like to update a collection named Lists which has several properties, one of which is an array of items. In the following code, I'm pushing a new task items in the items array. Everything works fine, however the update function does not sends back the updated collection, then I must perform another query on the database. Is there a more efficient way to do this ?
The nodejs/express code :
exports.addTaskToList = function(req, res) {
var listId = req.params.Id;
var taskId = req.params.TaskId;
Lists.update({_id: listId}, {$push: {items: taskId}}, {safe:true, upsert: true}, function(err, result){
if(err) {
console.log('Error updating todo list. ' + err);
}
else{
console.log(result + ' todo list entry updated - New task added');
Lists.findById(listId).populate('items').exec(function (err, updatedEntry) {
if (err) {
console.log('Unable to retrieve todo list entry.');
}
res.send(JSON.stringify(updatedEntry));
});
}
});
};
Furthermore, the array items is an array of ObjectIds. Those items are in a separate schema so in a separate collection. Is it possible to push the whole object and not only its _id so that there is not another collection created ?
Upvotes: 29
Views: 39272
Reputation: 20088
use findOneAndUpdate() method and in query parameter use option as { "new": true}
return this.sessionModel
.findOneAndUpdate({user_id: data.user_id}, {$set:{session_id: suuid}}, { "new": true})
.exec()
.then(data=>{
return {
sid: data.session_id
}
})
Upvotes: 34
Reputation: 4238
The update method doesn't return the updated document:
However, if we don't need the document returned in our application and merely want to update a property in the database directly, Model#update is right for us.
If you need to update and return the document, please consider one of the following options:
Traditional approach:
Lists.findById(listId, function(err, list) {
if (err) {
...
} else {
list.items.push(taskId)
list.save(function(err, list) {
...
});
}
});
Shorter approach:
Lists.findByIdAndUpdate(listId, {$push: {items: taskId}}, function(err, list) {
...
});
Upvotes: 27
Reputation: 1063
Regarding your last question:
Is it possible to push the whole object and not only its _id so that there is not another collection created ?
The answer is yes. You can store sub-documents within documents quite easily with Mongoose (documentation on sub-documents here). By changing your schema a little, you can just push your whole item object (not just item _id
) into an array of items defined in your List schema. But you'll need to modify your schema, for example:
var itemSchema = new Schema({
// Your Item schema goes here
task: 'string' // For example
});
var listSchema = new Schema({
// Your list schema goes here
listName: String, // For example...
items: [itemSchema] // Finally include an array of items
});
By adding an item
object to the items
property of a list, and then saving that list - your new item will be persisted to the List collection. For example,
var list = new List({
listName: "Things to do"
});
list.items.push({
task: "Mow the lawn"
});
list.save(function(error, result) {
if (error) // Handle error
console.log(result.list) // Will contain your item instance
});
So when you load your list, the items
property will come pre-populated with your array of items.
This is because Items will no longer persist it a separate collection. It will be persisted to the List collection as a sub-document of a List.
Upvotes: 1