0

I am trying to run a MongoDB query to update the value of one field with the value of another nested field. I have the following document:

{
  "name": "name",
  "address": "address",
  "times": 10,
  "snapshots": [
    {
      "dayTotal": 2,
      "dayHit": 2,
      "dayIndex": 2
    },
    {
      "dayTotal": 3,
      "dayHit": 3,
      "dayIndex": 3
    }
  ]
}

I am trying like this:

db.netGraphMetadataDTO.updateMany( 
    { },
    [{ $set: { times: "$snapshots.$[elem].dayTotal" } }],
    {   
        arrayFilters: [{"elem.dayIndex":{"$eq": 2}}],
        upsert: false,
        multi: true
    }
);

but got an error:

arrayFilters may not be specified for pipeline-syle updates

Yong Shun
  • 35,286
  • 4
  • 24
  • 46
Gentle Song
  • 90
  • 1
  • 7

1 Answers1

1

You can't use arrayFilters with aggregation pipeline for update query at the same time.

Instead, what you need to do:

  1. Get the dayTotal field from the result 2.

  2. Take the first matched document from the result 3.

  3. Filter the document from snapshots array.

db.netGraphMetadataDTO.updateMany({},
[
  {
    $set: {
      times: {
        $getField: {
          field: "dayTotal",
          input: {
            $first: {
              $filter: {
                input: "$snapshots",
                cond: {
                  $eq: [
                    "$$this.dayIndex",
                    2
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
],
{
  upsert: false,
  multi: true
})

Demo @ Mongo Playground

Yong Shun
  • 35,286
  • 4
  • 24
  • 46
  • but there still have one problem, $getField is not support under mongodb version 5.0, any instead ways? – Gentle Song Jan 11 '23 at 14:15
  • 1
    Hi, yes it's still possible to do. You need to add a `$set` stage to create an additional field used to store the value return from `{ $first: { ... } }`. And lastly, remove that field. [Demo](https://mongoplayground.net/p/waY8FHX_pN1) – Yong Shun Jan 11 '23 at 23:23