Add Field in nested array by other field

Hello i have simple collection:

{
    _id: 1,
    books: [
         { bookId: 55, c: 5},
         { bookId: 66, c: 6},
         { bookId: 77, c: 7},
    ]
}

How i can add new field by calulate other field?
here i add field “Z” to current found object in nested array by it calculate field “C”

updateOne(
{ 
  _id : 1, 
  'books.bookId' : 66 
} ,
{
  [
      {    $addFields: { "books.$.z" : { "$sum" : ["$books.$.c", 1]  } }    }
  ]
}

Expected result:

{
    _id: 1,
    books: [
         { bookId: 55, c: 5},
         { bookId: 66, c: 6, z:7},
         { bookId: 77, c: 7},
    ]
}

@alexov_inbox hi there ! !

That’s a great question imho.

I was not able to think of something simple. This is the aggregation:

db.collection.aggregate({
  "$addFields": {
    "books": {
      "$map": {
        "input": "$books",
        "as": "b",
        "in": {
          "$cond": {
            "if": {
              "$eq": [
                "$$b.bookId",
                55
              ]
            },
            "then": {
              "$mergeObjects": [
                "$$b",
                {
                  "z": {
                    "$sum": [
                      "$$b.c",
                      1
                    ]
                  }
                }
              ]
            },
            "else": "$$b"
          }
        }
      }
    }
  }
})

Example (and feel free to play around) here.

This will:

  • and modify only documents that pass some condition.
    • for each element in the books array
      • And assign it to the book fields using $addFields.

(the description goes from the inner part (condition) to the stage ($addFields)


You can paste that into a db.coll.update(<query>,<update>,<options>) basically all the stuff, included the square brackets [] go in <update>.

1 Like

ohhh so hardy…

I think there is an easy way. perhaps with the help of a new:

$getField
New in version 5.0 .

It could also be a JS function that does the same than the $map, but in friendly notation.

I didn’t know about $getField, thank you. I can’t really test much more now. But hopefully someone else will give a better idea…

Yes, thank you, your option works. I also roughly came to this option. But I think there is a short entry (possibly using $getField), let’s wait for more answers. I think mango is still able to combine ‘position operator $’ + (‘varible operator reference by prefix $’ or ‘combine with $getField’) how i try in my sample