5
votes

I am trying to create a very basic map-reduce example that also incorporates a query in the MapReduce api call.

My collection has lots of entries formatted as follows:

{ "_id" : { "$binary" : "PdYV4WMTAEyYMQHXJZfzvA==", "$type" : "03" }, 
    "firstname" : "Matthew", 
    "surname" : "Chambers", 
    "email" : "" }

The code is as follows:

var map = @"
function() {
    emit(this.surname, { count : 22 });
}";
var reduce = @"
function(key, emitValues) {
    return { count : emitValues[0].count };
}";

List<BsonValue> contactIds = new List<BsonValue>();
contactIds.Add(new Guid("A04FC88D-7BF7-443D-B5C3-EB11EE2B36DF"));
contactIds.Add(new Guid("26B690B3-5ED7-47F4-A878-3906E28BBC58"));
MongoDB.Driver.Builders.QueryConditionList queryList = MongoDB.Driver.Builders.Query.In("_id", BsonArray.Create(contactIds));
//var mr = personCollection.MapReduce(map, reduce);// THIS WORKS!    
var mr = personCollection.MapReduce(queryList, map, reduce); // THIS FAILS

It all works if I don't include the queryList in the MapReduce call. However, if I do include the queryList then I get the following runtime error:

Command 'mapreduce' failed: db assertion failure (response: { "assertion" : "'out' has to be a string or an object", "assertionCode" : 13606, "errmsg" : "db assertion failure", "ok" : 0 }) at MongoDB.Driver.MongoDatabase.RunCommandAs[TCommandResult](IMongoCommand command) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoDatabase.cs:line 621 at MongoDB.Driver.MongoCollection.MapReduce(BsonJavaScript map, BsonJavaScript reduce, IMongoMapReduceOptions options) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCollection.cs:line 788 at MongoDB.Driver.MongoCollection.MapReduce(IMongoQuery query, BsonJavaScript map, BsonJavaScript reduce) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Core\MongoCollection.cs:line 823 at HPSLucene.Models.Mongo.MapReduce() in C:\Inetpub\wwwroot\HPSLucene\HPSLucene\Models\Mongo.cs:line 158

Anyone know what the problem is? Thanks very much.

3
What version of the C# driver are you using? - AdaTheDev

3 Answers

7
votes

Looks like it has matched your call to a different overload to the one you think you are calling

i.e. you're intending to call the (query, map, reduce) overload but actually it's calling the (map, reduce, options) overload. This gives you the error as your third arg is not a valid options argument.

Try using the following overload: (query, map, reduce, options) It will then work as won't get confused as to what one to use.

e.g. to return the results of the M/R inline, and not store in a collection:

var mr = personCollection.MapReduce(queryList, map, reduce, 
                MapReduceOptions.SetOutput(MapReduceOutput.Inline));
3
votes

Btw, following AdaTheDev's answer this is what I ended up with:

List<BsonValue> contactIds = new List<BsonValue>();
contactIds.Add(new Guid("A04FC88D-7BF7-443D-B5C3-EB11EE2B36DF"));
contactIds.Add(new Guid("26B690B3-5ED7-47F4-A878-3906E28BBC58"));
MongoDB.Driver.Builders.QueryConditionList queryList = MongoDB.Driver.Builders.Query.In("_id", BsonArray.Create(contactIds));
MongoDB.Driver.Builders.MapReduceOptionsBuilder builder=new MongoDB.Driver.Builders.MapReduceOptionsBuilder();
builder.SetOutput(MongoDB.Driver.Builders.MapReduceOutput.Inline);
var mr = personCollection.MapReduce(map, reduce, builder);
0
votes

I created a test program to reproduce this and it appears that it is in fact calling the correct overload of MapReduce. But you have encountered a bug in the driver. I have created a JIRA case for it:

http://jira.mongodb.org/browse/CSHARP-193

Your final version is fine. By providing an explicit options parameter you are working around the bug.