Updating data type to an Object in mongoDB

坚强是说给别人听的谎言 提交于 2021-02-15 07:37:33

问题


I have changed one of the fields of my collection in mongoDB from an array of strings to an array of object containing 2 strings. New documents get inserted without any problem, but when a get method is called to get , querying all the documents I get this error:

Failed to decode 'Students'. Decoding 'photoAddresses' errored with: readStartDocument can only be called when CurrentBSONType is DOCUMENT, not when CurrentBSONType is STRING.

photoAddresses is the field that was changed in Students.

I was wondering is there any way to update all the records so they all have the same data type, without losing any data.

The old version of photoAdresses:

"photoAddresses" : ["something","something else"]

This should be updated to the new version like this:

"photoAddresses" : [{photoAddresses:"something"},{photoAddresses:"something else"}]

回答1:


The following aggregation queries update the string array to object array, only if the array has string elements. The aggregation operator $map is used to map the string array elements to objects. You can use any of the two queries.

db.test.aggregate( [
  { 
      $match: { 
          $expr: { $and: [ { $isArray: "$photo" }, 
                           { $gt: [ { $size: "$photo" }, 0 ] }
                         ] 
          }, 
          "photo.0": { $type: "string" }
      } 
  },
  {
      $project: {
          photo: { 
              $map: {
                   input: "$photo", 
                      as: "ph", 
                      in: { addr: "$$ph" } 
               } 
          }
      } 
  },
] ).forEach( doc => db.test.updateOne( { _id: doc._id }, { $set: { photo: doc.photo } } ) )


The following query works with MongoDB version 4.2+ only. Note the update operation is an aggregation instead of an update. See updateMany.

db.test.updateMany(
  { 
          $expr: { $and: [ { $isArray: "$photo" }, 
                           { $gt: [ { $size: "$photo" }, 0 ] }
                         ] 
          }, 
          "photo.0": { $type: "string" }
  },
  [
    {
      $set: {
          photo: { 
              $map: {
                   input: "$photo", 
                      as: "ph", 
                      in: { addr: "$$ph" } 
               } 
          }
      } 
    }
  ]
)



[EDIT ADD]: The following query works with version MongoDB 3.4:
db.test.aggregate( [
  { 
      $addFields: { 
          matches: {
              $cond: {
                  if: { $and: [ 
                          { $isArray: "$photoAddresses" }, 
                          { $gt: [ { $size: "$photoAddresses" }, 0 ] },
                          { $eq: [ { $type: { $arrayElemAt: [ "$photoAddresses", 0 ] } }, "string" ] }
                       ] },
                  then: true,
                  else: false
              }
          }
      }
  },
  {
      $match: { matches: true }
  },
  {
      $project: {
          photoAddresses: { 
              $map:  {
                   input: "$photoAddresses", 
                      as: "ph", 
                      in: { photoAddresses: "$$ph" } 
               } 
          }
      } 
  },
] ).forEach( doc => db.test.updateOne( { _id: doc._id }, { $set: { photoAddresses: doc.photoAddresses } } ) )


来源:https://stackoverflow.com/questions/59467973/updating-data-type-to-an-object-in-mongodb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!