我有大约25k个文档(原始json中为4 GB ),我想对其执行一些javascript操作,以使我的最终数据使用者(R)更容易访问这些数据,我想通过为每个更改添加一个新集合来对这些更改进行“版本控制”,但我不知道如何在没有reduce的情况下执行map/reduce。我想要一个一对一的文档映射--我从collection_1格式的25,356个文档开始,到collection_2格式的25,356个文档结束。
我可以用这个来破解它:
var reducer = function(key, value_array) {
return {key: value_array[0]}
}然后这样叫它:
db.flat_1.mapReduce(mapper, reducer, {keeptemp: true, out: 'flat_2'})(我的映射器只调用emit一次,第一个参数是字符串,第二个参数是最后一个文档。这是我真正想要的第二个参数的集合。)
但这似乎很尴尬,我甚至不知道它为什么有效,因为我的映射器中的emit调用参数并不等同于我的reducer的返回参数。另外,我最终得到了像这样的文档
{
"_id": "0xWH4T3V3R",
"value": {
"key": {
"finally": ["here"],
"thisIsWhatIWanted": ["Yes!"]
}
}
}这似乎没有必要。
而且,执行自己插入操作的游标甚至没有mapReduce快十分之一。我对MongoDB的了解还不够深入,无法对其进行基准测试,但我猜是因为50x速度较慢。有没有一种并行运行游标的方法?我不关心collection_2中的文档是否与collection_1中的文档顺序不同。
发布于 2010-08-31 07:43:22
当使用map/reduce时,你总是会得到
{ "value" : { <reduced data> } }为了删除value密钥,您必须使用finalize函数。
下面是将数据从一个集合复制到另一个集合的最简单方法:
map = function() { emit(this._id, this ); }
reduce = function(key, values) { return values[0]; }
finalize = function(key, value) { db.collection_2.insert(value); }然后,当您可以正常运行时:
db.collection_1.mapReduce(map, reduce, { finalize: finalize });发布于 2010-08-27 18:11:35
这看起来很尴尬,我甚至不知道它为什么有效,因为我的映射器中的emit调用参数并不等同于我的reducer的
参数。
它们是等效的。reduce函数接受T值的数组,并且应该以相同的T格式返回单个值。T的格式由您的map函数定义。reduce函数只返回值数组中的第一项,该数组的类型始终为T。这就是它工作的原因:)
你似乎走在正确的轨道上。我做了一些实验,似乎不能从map函数执行db.collection.save(),但可以从reduce函数执行此操作。您的map函数应该只构造所需的文档格式:
function map() {
emit(this._id, { _id: this.id, heading: this.title, body: this.content });
}map函数重用原始文档的ID。这应该可以防止任何重新减少步骤,因为没有任何值将共享相同的键。
reduce函数可以简单地返回null。但除此之外,您还可以将值写到单独的集合中。
function reduce(key, values) {
db.result.save(values[0]);
return null;
}现在,db.result应该包含转换后的文档,而不需要在临时集合中添加任何额外的map-reduce噪声。我实际上没有在大量数据上测试过这种方法,但是这种方法应该利用map-reduce函数的并行执行。
发布于 2016-04-18 04:44:14
当您访问mongo shell时,它接受一些Javascript命令,这样就更简单了:
map = function(item){
db.result.insert(item);
}
db.collection.find().forEach(map);https://stackoverflow.com/questions/3581058
复制相似问题