【问题标题】:Using DBCollection.mapReduce to change MongoDB schema: spurious nested "value" attribute使用 DBCollection.mapReduce 更改 MongoDB 架构:虚假嵌套“值”属性
【发布时间】:2018-04-19 19:16:44
【问题描述】:

我需要创建一个数据库补丁,将 MongoDB 集合的所有元素更新为新格式。 例如,粗略简化后,旧格式的文档如下:

{
  "_id" : ObjectId("572a7f30200cd11355083cd9"),
  "_class" : "Domain",
  "oldAttribute": 123
}

而新格式需要这样的文件:

{
  "_id" : ObjectId("572a7f30200cd11355083cd9"),
  "_class" : "Domain",
  "newAttribute": 123
}

我正在使用 MongoDB 的 Java API,并且数据库补丁也必须用 Java 编写,但不是编写一堆 Java 代码来修改文档,先读取它们然后再写回它们,我想我可以利用 DBCollection.mapReduce()MapReduceCommand.OutputType.REPLACE 直接在 MongoDB 中使用一小段 JavaScript 执行相同的操作,如下所示:

myCollection.mapReduce(map, reduce, "myCollection", MapReduceCommand.OutputType.REPLACE, null);

对于map 函数,我传递如下内容:

function () {
  var copy = {'_id': this._id, '_class': this._class, newAttribute: this.oldAttribute};
  emit(this._id, copy);
}

reduce 函数在技术上不应该被调用,因为键是唯一的,所以我只是在那里传递一个虚拟函数。

这似乎可行,但有一个问题:应用 map-reduce 后,集合中的所有文档现在都有一个嵌套的 value 属性:

{
  "_id": { "$oid" : "56c2371a200cd11088252111"},
  "value":
  {
    "_id": { "$oid" : "56c2371a200cd11088252111"},
    "_class": "Domain",
    "newAttribute": 123.0
  }
}

(此输出是从 Java 控制台粘贴的,因此格式略有不同)

简而言之,我的问题是:如何摆脱嵌套的value 属性并在顶层拥有所有属性(包括_id)?

【问题讨论】:

  • 为什么需要 mapReduce,为什么不直接使用带有 $rename 修饰符的更新?
  • 正如我在最初的问题中所说,它被大大简化了;我实际上不只是重命名一个字段;补丁修改了文档的整个结构,例如,字段被移动等等。
  • 你可以使用 $out 聚合。仍然不需要更慢的 MapReduce。

标签: java mongodb mapreduce mongodb-query


【解决方案1】:

如果要修改文档,可以使用带有$rename修饰符的更新。使用multi:true 运行更新将更新集合中的每个文档。

如果您希望更改显示为“原子”并且集合不分片,您可以使用 aggregate$out 以及此管道:

db.collection.aggregate([ 
    {$project:{_class:1, newAttribute:"$oldAttribute"}}, 
    {$out:"collection"}
]) 

$out 提供与原始集合名称相同的名称将用新转换的版本替换集合。

如果您想在不删除旧版本的情况下创建新版本的集合,只需将新集合名称指定给$out

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多