I use Mongo 4.4 and I try to perform an update with the aggregation pipeline using updateOne
that updates the nested array elements. In order to update the specific array member I use an arrayFilter
in the option but for some reason, I get the error message:
arrayFilters may not be specified for pipeline-style updates.
The query is something like this:
updateOne( { _id: <some_id>}, [ { $set: { 'arr.$[element]': <new_value> } }, { $set: { somefield: { '$cond': { <the condition content> } } } } ], { arrayFilters: [ {'element.id': <new_value>.id } ] } );
How to fix it?
EDIT 1:
An example of a document is:
{ _id: 932842242342354234, lastUpdateTime: <old time>, comments: [ { id: 390430, content: "original", lastUpdated: <sime time> } ], }
The query I want to do is update a comment and at the same time update the main object’s field lastEditTime
only if the content lastUpdated
has a time that is after the current lastEditTime
of the current document. So the update is:
updateOne( { _id: documentId}, [ { $set: { 'comments.$[element]': newComment } }, { $set: { lastUpdateTime: { '$cond': { if: { $gte: [newComment.lastUpdated, '$lastUpdateTime'] }, then: newComment.lastUpdated, else: '$lastUpdateTime', } } } } ], { arrayFilters: [ {'element.id': newComment.id } ] } );
So for example after an update with the comment:
{ id: 390430, content: "new content", lastUpdated: <new time> }
I want my main object to be:
{ _id: 932842242342354234, lastUpdateTime: <new time>, comments: [ { id: 390430, content: "new content", lastUpdated: <new time> } ], }
Advertisement
Answer
I think the arrayFilters
is not suitable for your scenario. Instead, using the aggregation pipeline.
With $map
to iterate every element in comments
array. If the element is matched with the id
to be updated, then update with newComment
object, else remain the existing value.
updateOne( { _id: documentId }, [ { $set: { 'comments': { $map: { input: "$comments", in: { $cond: { if: { $eq: [ "$$this.id", newComment.id ] }, then: newComment, else: "$$this" } } } } } }, { $set: { lastUpdateTime: { '$cond': { if: { $gte: [newComment.lastUpdated, '$lastUpdateTime'] }, then: newComment.lastUpdated, else: '$lastUpdateTime', } } } } ] );