MongoDB:根据现有字段值更新集合中的嵌套值

时间:2019-02-17 00:35:42

标签: mongodb mongodb-query aggregation-framework

如果它们是字符串类型,我想在整个集合中更新嵌套_id。

如果我有看起来像这样的对象...

user : {
    _id: ObjectId('234wer234wer234wer'),
    occupation: 'Reader',
    books_read: [
        {
           title: "Best book ever",
            _id: "123qwe234wer345ert456rty"
        },
        {
           title: "Worst book ever",
            _id: "223qwe234wer345ert456rty"
        },
        {
           title: "A Tail of Two Cities",
            _id: ObjectId("323qwe234wer345ert456rty")
        }
    ]
}

我想将_Ids的类型从字符串更改为ObjectId

我该怎么办??

我过去曾经做过“ this” ...但这在非嵌套项目上起作用-我需要更改嵌套值

 db.getCollection('users')
.find({
  $or: [
    {occupation:{$exists:false}},
    {occupation:{$eq:null}}
  ]
})
.forEach(function (record) {
  record.occupation = 'Reader';
  db.users.save(record);
});

任何帮助-我试图避免在应用服务器上编写一系列循环来进行数据库调用-因此我希望直接在“ mongo”中找到一些东西

1 个答案:

答案 0 :(得分:0)

在引用现有字段时,没有一种方法(非$rename)更新文档上的操作-MongoDB: Updating documents using data from the same document

因此,您需要编写一个脚本(类似于您用findeach发布的脚本),以正确的_id类型重新创建这些文档。要查找要更新的子文档,可以使用$type运算符。像db.coll.find({nestedField._id: {$type: 'string' }})这样的查询应该找到所有包含不良子文档的完整文档,或者您可以使用$match$unwind进行汇总查询,以仅获取子文档

db.coll.aggregate([
  { $match: {'nestedField._id': {$type: 'string' }}}, // limiting to documents that have any bad subdocuments
  { $unwind: '$nestedField'}, // creating a separate document in the pipeline for each entry in the array
  { $match: {'nestedField._id': {$type: 'string' }}}, // limiting to only the subdocuments that have bad fields
  { $project: { nestedId: 'nestedField._id' }} // output will be: {_id: documentedId, nestedId }
])

  

我试图避免在应用服务器上编写一系列循环来进行数据库调用-所以我希望直接在'mongo'中找到一些东西

可以直接在mongo上运行js代码以避免进行api调用,但是我认为没有任何方法可以避免循环遍历文档。