Search code examples
phpmongodbaggregation-frameworkphp-mongodb

Add computed field to each array element using another field as value


Structure:

"entity": [
    {
        "_id": {
            "$oid": "5bbf6e6d69a634eeb5a32a0e"
        },
        "Extension Id": "PR00027173",
        "Files": [
            {
                "Locale": "en_WW",
                "FileExtension": "ai",
                "Number": []
            },
            {
                "Locale": "sv_SE",
                "Type": "Technical drawing",
                "FileExtension": "eps",
                "Number": []
            }
        ]
    },
    {
        "_id": {
            "$oid": "5bbf6e6d69a634eeb5a32b7c"
        },
        "Extension Id": "PR00027174",
        "Files": [
            {
                "Locale": "en_WW",
                "FileExtension": "ai",
                "Number": []
            },
            {
                "Locale": "sv_SE",
                "Type": "Technical drawing",
                "FileExtension": "eps",
                "Number": []
            }
        ]
    }
]

I want to add computed field (Number) in each array element in my Files field and set its value as other field from the same element i.e Type. I've tried it using aggregate framework, but each time i set the value it takes all the values from whole array i.e:

"Files": [
            {
                "Locale": "en_WW",
                "FileExtension": "ai",
                "Number": [
                    "ai",
                    "eps"
                ]
            },
            {
                "Locale": "sv_SE",
                "Type": "Technical drawing",
                "FileExtension": "eps",
                "Number": [                        
                    "ai",
                    "eps"
                ]
            }
]

Is it possible to set new field Number value as i.e FileExtension but only from the same element instead of whole array? This is how my projection in aggregate looks like:

  ["projection"]=> array(1) {
["Files.Number"]=>
string(29) "$Files.FileExtension"}}

Solution

  • This is not possible with standard projection as it is an array. You have to use array operator $map to set the array elements.

    Something like

    db.collection.aggregate([
      ...other stages..
      {"$addFields":{
          "Files":{
            "$map":{
             "input":"$Files",
             "in":{
                 "Locale": "$$this.Locale",
                 "FileExtension": "$$this.FileExtension",
                 "Number":"$$this.FileExtension"
              }
            }
          }
       }}
    ])