我是MongoDB和MapReduce的新手。我需要做一些MapReduce上的集合在我的数据库。MAP
和REDUCE_MAX
函数可以工作,因为我能够在Mongo交互式shell (v.1.8.2)中完成我的需求。然而,我得到一个错误,试图执行相同的事情使用Mongo Java驱动程序(v. 2.6.3)
我的MAP
和REDUCE_MAX
函数是这样的:
String MAP =
"function(){" +
"if(this.type != "checkin"){return;}" +
"if(!this.venue && !this.venue.id){return;}" +
"emit({userId:this.userId, venueId:this.venue.id}, {count:1});" +
"};";
String REDUCE_MAX =
"function(key, values){" +
"var res = {count:0};" +
"values.forEach(function(value){result.count += value.count;});" +
"return res;" +
"};";
这是我正在执行的命令:
MapReduceOutput sum = collection
.mapReduce(MAP, REDUCE_MAX, null, null);
这是我得到的错误:
com.mongodb.CommandResult$CommandFailure: command failed [command failed [mapreduce] { "assertion" : "wrong type for BSONElement (replace) 10 != 2" , "assertionCode" : 13111 , "errmsg" : "db assertion failure" , "ok" : 0.0}
我不知道哪个BSONElement有错误的类型。我已经在谷歌上搜索过assertionCode: 13111
了。我也检查了MongoDB日志,但没有发现任何线索。
有没有人有一个想法,我可能错过/做错了什么?如果你们需要更多细节,请告诉我。
今天我无意中发现了我的错误,并打算在这里分享解决方案,以防有人遇到类似的问题。
mapReduce
方法的调用导致了这个问题:
MapReduceOutput sum = collection
.mapReduce(MAP, REDUCE_MAX, null, null);
看一下这个方法的Javadoc:
/**
* performs a map reduce operation
* Runs the command in REPLACE output mode (saves to named collection)
*
* @param map
* map function in javascript code
* @param outputTarget
* optional - leave null if want to use temp collection
* @param reduce
* reduce function in javascript code
* @param query
* to match
* @return
* @throws MongoException
* @dochub mapreduce
*/
它声明命令以REPLACE
作为输出模式执行,如果想要临时收集,outputTarget
应该是null
。
不幸的是,mapReduce
方法中使用的构造函数MapReduceCommand
,只有在OutputType
被设置为INLINE
(根据MapReduceCommand.getOutputTarget()
的Javadoc)时,才允许outputTarget
为空。
所以我所要做的就是把第三个参数从null
改为String
,像这样:
MapReduceOutput sum = collection
.mapReduce(MAP, REDUCE_MAX, "tmp", null);
这是我在试图弄清楚为什么它不起作用时唯一没有摆弄过的参数。
您可能还想尝试:
MapReduceOutput sum = collection.mapReduce(MAP, REDUCE_MAX, null,
OutputType.INLINE, null);
如果你想有一个内联集合而不给它一个名字