我已经导入了一个包含多个文档的数据集,每个文档包含一个流派属性,它的值是string - A json string,比如"[{'field1':'value1'}, {'field2':'value2'}]",请注意quote我希望这是对象的数组

{
  "genres": "[{'id': 16, 'name': 'Animation'}, {'id': 35, 'name': 'Comedy'}, {'id': 10751,'name': 'Family'}]"
}

以上字符串值要按以下方式转换

{
    "title": "Toy story collection",
    "genres": [
        {'id': 16, 'name': 'Animation'}, 
        {'id': 35, 'name': 'Comedy'}, 
        {'id': 10751,'name': 'Family'}
    ]
},
{
    "title": "Shrek",
    "genres": [
        {'id': 16, 'name': 'Animation'} 
    ]
},
{
    "title": "Full House",
    "genres": [
        {'id': 10751,'name': 'Family'}
    ]
}

这将使我能够按如下方式搜索记录

db.moviesCollection.find({"genres.name":"Animation"})

我能想到的一个解决方案是通过php或javascrip逐个加载每个文档,然后开始转换它.

有什么办法吗?I can update documentes directly through mongodb itself美元,不用任何编程语言.

另一个回答提到了类似于Follow的内容,但没有提到他们是否使用任何语言.

db.movies_metadata.find({}).snapshot().forEach(function (el){el.genres=JSON.parse(el.genres);db.movies_metadata.save(el)});

如果我直接在控制台上运行上面的代码,我会看到以下错误.

未捕获异常:TypeError:DB.Movies_metadata.find(...).快照 不是函数:@(shell ):1:1

Updated Answer:个 在获得一个很好的答案之后,下面是我的最后一个更新查询,我使用merge而不是replace,因为我想保留其余的属性

db.movies_metadata.aggregate([
  {
    "$project": {
      "genres": {
        "$function": {
          "body": "function(genres) { genres = genres.replace(/'/g, '\"'); return JSON.parse(genres) }",
          "args": [
            "$genres"
          ],
          "lang": "js"
        }
      }
    }
  },
  {
    "$merge": {
      "into": "movies_metadata",
      "on": "_id",
      "whenMatched": "merge",
      "whenNotMatched": "insert"
    }
  }
])

推荐答案

首先,您提供的值不是有效的JSON,应该是这样的:

{
    "genres": "[{\"id\":16,\"name\":\"Animation\"},{\"id\":35,\"name\":\"Comedy\"},{\"id\":10751,\"name\":\"Family\"}]"
}

现在,有一种方法可以在MongoDB内部使用$function阶段解析这个JSON,并使用$merge写入集合,前提是您有MongoDB 4.4版或更高版本,如下所示:

db.collection.aggregate([
  {
    "$project": {
      "genres": {
        "$function": {
          "body": "function(genres) { return JSON.parse(genres) }",
          "args": [
            "$genres"
          ],
          "lang": "js"
        }
      }
    }
  },
  {
    "$merge": {
      "into": "collectionName",
      "on": "_id",
      "whenMatched": "replace",
      "whenNotMatched": "insert"
    }
  }
])

看,它能工作here分钟.

此查询将使用您的现有数据:

db.collection.aggregate([
  {
    "$project": {
      "genres": {
        "$function": {
          "body": "function(genres) { genres = genres.replace(/'/g, '\"'); return JSON.parse(genres) }",
          "args": [
            "$genres"
          ],
          "lang": "js"
        }
      }
    }
  },
  {
    "$merge": {
      "into": "collectionName",
      "on": "_id",
      "whenMatched": "replace",
      "whenNotMatched": "insert"
    }
  }
])

playground link号.

Mongodb相关问答推荐

在一个视图中连接两个集合MongoDB;展开有什么作用?

从MongoDB中的一个非空字段获取值

Mongo DB-如果一个特定字段有多个文档匹配,则更新文档字段

在提供的文档(_Id)之后和之前,是否有一个Mongo操作来获取已排序(和/或过滤)集合中的文档计数?

DTO 验证适用于 POST,但不适用于 PUT

Mongoose updateMany 以及 Where 和 orWhere?

使用 $addFields 将字段添加到 $lookup 结果中的每个项目

如何过滤查找mongodb的结果

MongoDB 支持的最 Big Data 库数

System.FormatException occurred in MongoDB.Bson.dll - XXX is not a valid 24 digit hex string

NodeJS + MongoDB:使用 findOne () 从集合中获取数据

mongodb上不区分大小写的查询

Docker 内部的 Mongo 身份验证

spring-data-mongo - 可选查询参数?

MongoDB - 文件大小巨大且不断增长

mongo - Ruby连接问题

使用 MongoDB 的 map/reduce 来分组两个字段

将新值推送到 mongodb 内部数组 - mongodb/php

带有 either or查询的mongoose findOne

mongoose查询返回 null