Reputation: 6289
I am trying to figure out how to use the $addFields
operation within a function I'm using to update a document. The logic to generate this field is simple enough, I just pull out the last object in an array, like so:
{
$addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } }
}
Now I need to figure out how to get this aggregation into my update function, the relevant code of which looks like this:
updatedDoc = await request.findOneAndUpdate(
StaffMember,
{
_id: request.parameters.id
},
req,
{
new: true
}
);
What I tried doing was this:
updatedDoc = await request.findOneAndUpdate(
StaffMember,
{
_id: request.parameters.id
},
req,
{
new: true
}
);
await request.aggregate(updatedDoc, [
{
$addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } }
}
]);
... but this gives me an error:
TypeError: mongooseModelObject.aggregate is not a function
Would I use the $addFields operator with $set, like so?
updatedDoc = await request.findOneAndUpdate(
StaffMember,
{
_id: request.parameters.id
},
{
$set: {
req,
$addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } }
}
},
{
new: true
}
);
How does one run an aggregation as part of a function like this? A simple example would help me understand how this needs to be done -- if indeed it can be done.
Of course, there are other ways to do this, but I'd like to take advantage of a mongo-specific way to handle this, using a mongo operation like $addFields
. What would this look like?
By the way, the wrapper function I'm using with aggregate looks like this:
async aggregate(mongooseModelObject, aggregateObject = {}) {
try {
return await mongooseModelObject.aggregate(aggregateObject).exec();
} catch (err) {
this.sendError(err);
}
}
Upvotes: 4
Views: 6748
Reputation: 1
db.col.aggregate
won't change data in collection but db.col.insertMany
will
db.temperatures.updateMany({}, [{$addFields: {"fields-name": "value"}}])
Upvotes: 0
Reputation: 2918
Starting from MongoDB 4.2, findAndUpdateOne
, updateOne
, updateMany
can accept an aggregation pipeline for the update.
const updatedDocument = await DocumentModel.updateOne({ _id: id }, [
{
$set: {
items: items,
}
},
{
$addFields: { totalItems: { $sum: '$items.quantity' } },
}
],
{ new: true } // to return updated document
);
Upvotes: 2
Reputation: 49985
Basically you can't use aggregate
as part of an update. The only way to update the data using $addFields
is to use $out like this:
db.col.aggregate([
{ $addFields: { activeWorkflow: { $arrayElemAt: ["$workflow", -1.0] } } },
{ $out: "col" }
])
but this will unfortunately add activeWorkflow
for all the documents in col
.
For regular .update()
you can't refer to another field so the only way to do that for single doc is use to findOne()
to get that document, then add new field in your application logic and then use update()
or save()
to store that updated document (old question here).
Upvotes: 4