Update nested objects array to string array

Hi , I have below collection

{
    "_id" : ObjectId("5d7e6c54c23c210001108556"),
    “parentId" : "5d0162ba69cf130001a16115",
    "tasks" : [
        {
            "_id" : "ae60a8f1",
            "taskMetaDataIds” : [
                ObjectId("5d55a648e2f7320001e578ac")
            ],
            "name" : “meta 3"
        },
        {
            "_id" : "07544d96",
            "taskMetaDataIds" : [
                 ObjectId("5d55a648e2f732676676676”),
                 ObjectId("5d55a648e2612333556888”)
            ],
            "name" : “meta 2"
        },
        
    ],
    "name" : “New Topic",
    "createdBy" : "01526151-8303-450f-b08b-b36a1760b774",
    "createdDate" : ISODate("2019-09-15T16:52:36.150+0000"),
    "updatedDate" : ISODate("2019-09-15T16:52:36.150+0000")
}

I am looking for below output . Is there an operator which can directly convert the array of objects into array of strings as shown below. I can do it with a script by looping over the taskMetaDataIds array but I am looking to use a direct mongo operator which suits my purpose.

{
    "_id" : ObjectId("5d7e6c54c23c210001108556"),
    “parentId" : "5d0162ba69cf130001a16115",
    "tasks" : [
        {
            "_id" : "ae60a8f1",
            "taskMetaDataIds” : [
                "5d55a648e2f7320001e578ac"
            ],
            "name" : “meta 3"
        },
        {
            "_id" : "07544d96",
            "taskMetaDataIds" : [
                "5d55a648e2f732676676676”,
		“5d55a648e2612333556888”
            ],
            "name" : “meta 2"
        },
        
    ],
    "name" : “New Topic",
    "createdBy" : "01526151-8303-450f-b08b-b36a1760b774",
    "createdDate" : ISODate("2019-09-15T16:52:36.150+0000"),
    "updatedDate" : ISODate("2019-09-15T16:52:36.150+0000")
}

I strongly recommend not to do that.

  1. String representation of an ObjectId is bigger
  2. String representation of an ObjectId is slower to compare
  3. Cannot use localField, foreignField in $lookup since you need to convert the string to match the ObjectId

To illustrate point 1:

mongosh> id_as_oid.find()
< { _id: ObjectId("63643a258d20af6265841ef7") }
  { _id: ObjectId("63643a288d20af6265841ef8") }
  { _id: ObjectId("63643a298d20af6265841ef9") }
  { _id: ObjectId("63643a2b8d20af6265841efa") }
  { _id: ObjectId("63643a2c8d20af6265841efb") }
  { _id: ObjectId("63643a3d8d20af6265841efc") }
  { _id: ObjectId("63643a3e8d20af6265841efd") }
  { _id: ObjectId("63643a3f8d20af6265841efe") }
  { _id: ObjectId("63643a408d20af6265841eff") }
  { _id: ObjectId("63643a418d20af6265841f00") }
mongosh> id_as_string.find()
> { _id: '63643a258d20af6265841ef7' }
  { _id: '63643a288d20af6265841ef8' }
  { _id: '63643a298d20af6265841ef9' }
  { _id: '63643a2b8d20af6265841efa' }
  { _id: '63643a2c8d20af6265841efb' }
  { _id: '63643a3d8d20af6265841efc' }
  { _id: '63643a3e8d20af6265841efd' }
  { _id: '63643a3f8d20af6265841efe' }
  { _id: '63643a408d20af6265841eff' }
  { _id: '63643a418d20af6265841f00' }
mongosh> id_as_oid.stats()
< {
  ns: 'test.is_as_oid',
  size: 220,
  count: 10,
  avgObjSize: 22,
  storageSize: 20480,
  freeStorageSize: 0,
  capped: false,
  nindexes: 1,
  indexBuilds: [],
  totalIndexSize: 20480,
  totalSize: 40960,
  indexSizes: { _id_: 20480 },
  /* other fields redacted out */
  }
mongosh> id_as_string.stats()
< {
  ns: 'test.is_as_string',
  size: 390,
  count: 10,
  avgObjSize: 39,
  storageSize: 36864,
  freeStorageSize: 16384,
  capped: false,
  nindexes: 1,
  indexBuilds: [],
  totalIndexSize: 36864,
  totalSize: 73728,
  indexSizes: { _id_: 36864 },
  /* other fields redacted out */
  }

But if you insist. You will need $map because you have arrays. You will need $convert, obviously. You will also need $merge to store back the result into the original collection.

Thanks for the reply.
I need to do this as it a bad data which we need to fix.

Could you please elaborate on the solution you suggested?

Something like

2 Likes