How to map array of object and convert string value to number in mongodb?

Viewed 954

Here I have documents with details field as an array:

 {   
        "_id" : ObjectId("60ae0b29ab282518443c7ac5"),
        "details": [
              {
                "label": "Asset title",
                "value": "S1",
              },
              {
                "label": "Total Cost",
                "value": "250",
              },
              {
                "label": "Possession Status",
                "value": "Available",
              },
              {
                "label": "Estimated Monthly Rent",
                "value": "15.5",
              }
            ]
    },
    {   
        "_id" : ObjectId("60ae0b29ab282518443c7ac8"),
        "details": [
              {
                "label": "Asset title",
                "value": "S2",
              },
              {
                "label": "Total Cost",
                "value": "455.5",
              },
              {
                "label": "Possession Status",
                "value": "Available",
              },
              {
                "label": "Estimated Monthly Rent",
                "value": "30",
              }
            ]
    }

So I am trying to $project this array of objects by Mapping the array of objects and check if the label is "Total Cost" or "Estimated Monthly Rent", then I want to convert their string values to number. For Ex : if {label = "Total Cost"} , then : {"$toDouble" : value} and if {label = "Estimated Monthly Rent"} , then : {"$toDouble" : value}

I am trying this but getting error.

 db.collection.aggregate([
       {
             "$project": {
                                   
                    "data": {
                         "$map": {
                                "input": "$details", 
                                 "as": "val", 
                                 "in": {
                                 "$cond":{ if: {"$$val.label": "Total Cost"} , then: { "$toDouble" : "$$val.value"}},
                                 "$cond":{ if: {"$$val.label": "Estimated Monthly Rent"} , then: { "$toDouble" : "$$val.value"}}
                                  }
                         }
                     } 
              }
        }
    ])
2 Answers

check condition with $in operator and if match then return converted value otherwise return existing object

db.collection.aggregate([
  {
    "$project": {
      "data": {
        "$map": {
          "input": "$details",
          "as": "val",
          "in": {
            $cond: [
              { $in: ["$$val.label", ["Total Cost", "Estimated Monthly Rent"]] },
              {
                label: "$$val.label",
                value: { $toDouble: "$$val.value" }
              },
              "$$val"
            ]
          }
        }
      }
    }
  }
])

Playground

The problem with your query is you are using two $cond keys, within the in field, using only one and use $or operator. Another thing is within aggregation pipeline use $eq for equality matching, and lastly don't miss the else clause in $cond.

This query works:

db.collection.aggregate([
  {
    "$project": {
      "data": {
        "$map": {
          "input": "$details",
          "as": "val",
          "in": {
            "$cond": {
              if: {
                $or: [
                  {
                    "$eq": [
                      "$$val.label",
                      "Total Cost"
                    ]
                  },
                  {
                    "$eq": [
                      "$$val.label",
                      "Estimated Monthly Rent"
                    ]
                  }
                ]
              },
              then: {
                "$toDouble": "$$val.value"
              },
              else: {
                "$toString": "$$val.value"
              }
            }
          }
        }
      }
    }
  }
])

Check it working here.

Related