Alias name is changing the output JSON structure

Data

  [
      {
    "id": 1,
    "name": "Afghanistan",
    "iso3": "AFG",
    "iso2": "AF",
    "states": [
      {
        "id": 3901,
        "name": "Badakhshan",
        "state_code": "BDS"
      },
      {
        "id": 3871,
        "name": "Badghis",
        "state_code": "BDG"
      },
      {
        "id": 3875,
        "name": "Baghlan",
        "state_code": "BGL"
      },
      {
        "id": 3884,
        "name": "Balkh",
        "state_code": "BAL"
      }
    ]
      },
      {
    "id": 2,
    "name": "Algeria",
    "iso3": "DZA",
    "iso2": "DZ",
    "states": [
      {
        "id": 1118,
        "name": "Adrar",
        "state_code": "01"
      },
      {
        "id": 1119,
        "name": "Aïn Defla",
        "state_code": "44"
      }
    ]
      }
    ]

Desired output

{"_id":ObjectId("61703274bc1cd0c9d6f235f1"),"iso2":"AF","states":[{"name":"Badakhshan","statecode":"BDS"},{"name":"Badghis","statecode":"BDG"},{"name":"Baghlan","statecode":"BGL"},{"name":"Balkh","statecode":"BAL"}]}

For below query for state_code

db.countries.find({})
   .projection({"iso2":1, "states.name":1, "states.state_code":1})
   .where({"iso2":"AF"})

Output

{"_id":ObjectId("61703274bc1cd0c9d6f235f1"),"iso2":"AF","states":[{"name":"Badakhshan","state_code":"BDS"},{"name":"Badghis","state_code":"BDG"},{"name":"Baghlan","state_code":"BGL"},{"name":"Balkh","state_code":"BAL"}]}

On using alias name in query

db.countries.find({})
   .projection({"iso2":1, "states.name":1, "statecode":"$states.state_code"})
   .where({"iso2":"AF"})

Output

{"_id":1,"iso2":"AF","states":[{"name":"Badakhshan"},{"name":"Badghis"},{"name":"Baghlan"},{"name":"Balkh"}],"statecode":["BDS","BDG","BGL","BAL"]}

Not getting why it is showing different behavior in both cases

Hello @Akshay_Kumar5, Welcome to MongoDB developer forum,

The project part will select the present properties from states array,

If we access property by $ ($states.state_code) reference from the array of objects then it will return an array of values,

As per your expected result, you are trying to rename the field name from state_code to statecode property in states array of objects.

You have to use aggregation pipeline operator $map,

db.collection.aggregate([
  {
    $match: {
      "iso2": "AF"
    }
  },
  {
    $project: {
      "iso2": 1,
      "states": {
        $map: {
          input: "$states",
          in: {
            name: "$$this.name",
            statecode: "$$this.state_code"
          }
        }
      }
    }
  }
])

If you want to use this in find method then it is possible to use Expression Operators from MongoDB 4.4,

db.countries.find({})
   .projection({
     "iso2": 1, 
     "states": {
        $map: {
          input: "$states",
          in: {
            name: "$$this.name",
            statecode: "$$this.state_code"
          }
        }
     }
   })
   .where({"iso2":"AF"})
1 Like