问题
I'm pretty new to MongoDB and MapReduce. I need to do some MapReduce on a collection in my DB. The MAP
and REDUCE_MAX
functions work, since I was able to accomplish my needs in the Mongo interactive shell (v.1.8.2). However, I get an error trying to perform the same thing using the Mongo Java Driver (v. 2.6.3)
My MAP
and REDUCE_MAX
functions look like this:
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;" +
"};";
This is the command I'm executing:
MapReduceOutput sum = collection
.mapReduce(MAP, REDUCE_MAX, null, null);
This is the error I get:
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}
I don't know which BSONElement has the wrong type. And I've already googled the assertionCode: 13111
. I've also checked in the MongoDB log, but did not find any clues there.
Does anyone have an idea, what I could be missing/doing wrong? If you guys need more details, just let me know please.
回答1:
Today I stumbled upon my mistake and figured to share the solution here, just in case somebody encounters a similar problem.
The invocation of the mapReduce
method was causing the problem:
MapReduceOutput sum = collection
.mapReduce(MAP, REDUCE_MAX, null, null);
Have a look at the Javadoc for this method:
/**
* 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
*/
It states that the command is executed using REPLACE
as output mode and that if one wants a temporary collection, the outputTarget
should be null
.
Unfortunately though, the constructorMapReduceCommand
, which is used in the mapReduce
method, only allows the outputTarget
to be nullable if the OutputType
is set to INLINE
(according to the Javadoc of MapReduceCommand.getOutputTarget()
).
So all I had to do is to change the third parameter from null
to some String
, like so:
MapReduceOutput sum = collection
.mapReduce(MAP, REDUCE_MAX, "tmp", null);
This was like the only parameter I had not played around with while trying to figure out why it didn't work. I hope somebody might find this helpful.
回答2:
You might also want to try:
MapReduceOutput sum = collection.mapReduce(MAP, REDUCE_MAX, null,
OutputType.INLINE, null);
if you want to have an inline collection without giving it a name
来源:https://stackoverflow.com/questions/7306329/mapreduce-using-mongodb-java-driver-failes-with-wrong-type-for-bsonelement-asser