Home > Enterprise >  Formatting dates with $dateToString in nested arrays
Formatting dates with $dateToString in nested arrays

Time:08-10

I have a collection of documents where each document represents a location of charging stations. I'm trying to use $map and $dateToString to transform each last_updated field into a string and drop the milliseconds portion of the datetime. There can be up to 3 last_updated fields on a location. A top level last_updated, a last_updated for each evse within an evses array, and a last_updated field within each connector of each evse. It is also possible for the evses array to not be present.

Here is an example of 2 locations:

[
    {
        "id" : "A",
        "name" : "Meades Park",
        "evses" : [
            {
                "uid" : "B",
                "connectors" : [
                    {
                        "id" : "C",
                        "standard" : "IEC_62196_T1",
                        "last_updated" : ISODate("2021-02-18T23:54:56.000Z")
                    }
                ],
                "last_updated" : ISODate("2021-02-18T23:54:56.000Z")
            },
            {
                "uid" : "D",
                "connectors" : [
                    {
                        "id" : "E",
                        "standard" : "IEC_62196_T1",
                        "last_updated" : ISODate("2021-02-18T23:54:56.000Z")
                    }
                ],
                "last_updated" : ISODate("2021-02-18T23:54:56.000Z")
            }
        ],
        "last_updated" : ISODate("2021-12-14T23:42:06.000Z")
    },
    {
        "id" : "F",
        "name" : "5th Avenue",
        "last_updated" : ISODate("2022-01-12T13:12:01.000Z")
    }
]

I have my query working for the top level last_updated field and the evses.last_updated field, but I am having trouble modifying the evses.connectors.last_updated field. This is my query:

db.collection.aggregate([
    {
        $addFields: {
            last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$last_updated' } },
            evses: {
                $map: {
                    input: '$evses',
                    as: 'evse',
                    in: {
                        {
                            $mergeObjects: [
                                '$$evse',
                                { last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$$evse.last_updated' } } }
                            ]
                        }
                    }
                }
            }
        }
    }
])

Is it possible to do another $map within the $map.in object? I was able to get this working by turning in into an array, but this changed the way the data was returned.

Here is an example of my query using $map.in as an array:

db.collection.aggregate([
    {
        $addFields: {
            last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$last_updated' } },
            evses: {
                $map: {
                    input: '$evses',
                    as: 'evse',
                    in: [
                        {
                            $mergeObjects: [
                                '$$evse',
                                { last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$$evse.last_updated' } } }
                            ]
                        },
                        {
                            $map: {
                                input: '$$evse.connectors',
                                as: 'connector',
                                in: {
                                    $mergeObjects: [
                                        '$$connector',
                                        { last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$$connector.last_updated' } } }
                                    ]                              
                                }
                            }                    
                        }
                    ]
                }
            }
        }
])

In this case the returned documents look like this:

[
    {
        "id" : "A",
        "name" : "CHARGEPOINT WVCC 1684DELL 1",
        "evses" : [
            [
                {
                    "uid" : "B",
                    "connectors" : [
                        {
                            "id" : "C",
                            "standard" : "IEC_62196_T1",
                            "last_updated" : ISODate("2021-02-18T23:54:56.000 0000")
                        }
                    ],
                    "last_updated" : "2021-02-18T23:54:56Z"
                },
                [
                    {
                        "id" : "C",
                        "standard" : "IEC_62196_T1",
                        "last_updated" : "2021-02-18T23:54:56Z"
                    }
                ]
            ],
            [
                {
                    "uid" : "D",
                    "connectors" : [
                        {
                            "id" : "E",
                            "standard" : "IEC_62196_T1",
                            "last_updated" : ISODate("2021-02-19T22:15:43.000 0000")
                        }
                    ],
                    "last_updated" : "2021-02-19T22:15:43Z"
                },
                [
                    {
                        "id" : "E",
                        "standard" : "IEC_62196_T1",
                        "last_updated" : "2021-02-19T22:15:43Z"
                    }
                ]
            ]
        ],
        "last_updated" : "2021-12-14T23:42:06Z"
    },
    {
        "id" : "F",
        "name" : "5th Avenue",
        "last_updated" : "2022-01-12T13:12:01Z",
        evses: null
    }
]

Is it possible to perform a $map within another $map without duplicating the evses.connectors array and nesting them in another array?

CodePudding user response:

Your query should be as below:

  1. Remove the [] from in for the $map.

  2. Merge objects for $$evse, last_updated document and connectors document.

db.collection.aggregate([
  {
    $addFields: {
      last_updated: {
        $dateToString: {
          format: "%Y-%m-%dT%H:%M:%SZ",
          date: "$last_updated"
        }
      },
      evses: {
        $map: {
          input: "$evses",
          as: "evse",
          in: {
            $mergeObjects: [
              "$$evse",
              {
                last_updated: {
                  $dateToString: {
                    format: "%Y-%m-%dT%H:%M:%SZ",
                    date: "$$evse.last_updated"
                  }
                }
              },
              {
                connectors: {
                  $map: {
                    input: "$$evse.connectors",
                    as: "connector",
                    in: {
                      $mergeObjects: [
                        "$$connector",
                        {
                          last_updated: {
                            $dateToString: {
                              format: "%Y-%m-%dT%H:%M:%SZ",
                              date: "$$connector.last_updated"
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Sample Mongo Playground

  • Related