【发布时间】: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