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>
}
],
}
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',
}
}
}
}
]
);