在mongoDB中将数据类型更新为对象 [英] Updating data type to an Object in mongoDB

查看:77
本文介绍了在mongoDB中将数据类型更新为对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将mongoDB中集合的字段之一从字符串数组更改为包含2个字符串的对象数组.插入新文档没有任何问题,但是当调用get方法来获取,查询所有文档时,我得到此错误:

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:

无法解码学生".解码"photoAddresses"错误使用:readStartDocument仅在CurrentBSONType为文档,而不是当CurrentBSONType为STRING时.

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

photoAddresses是在学生"中更改的字段.

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.

photoAdresses的旧版本:

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"}]

推荐答案

仅当数组具有字符串元素时,以下聚合查询才会将字符串数组更新为对象数组.聚合运算符 $ map 用于映射将 string 数组元素添加到 objects .您可以使用两个查询中的任何一个.

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 } } ) )


以下查询仅适用于MongoDB 4.2+版本.请注意,更新操作是 aggregation ,而不是 update .参见 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" } 
               } 
          }
      } 
    }
  ]
)



[编辑添加]:以下查询适用于 MongoDB 3.4 版本:



[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 } } ) )

这篇关于在mongoDB中将数据类型更新为对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆