[CSHARP-581] MapReduce output to a collection in a different database fails with auth turned on Created: 27/Sep/12  Updated: 20/Mar/14  Resolved: 04/Apr/13

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 1.6
Fix Version/s: 1.8

Type: Improvement Priority: Major - P3
Reporter: Robert Stam Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to CSHARP-603 Support SASL Authentication Against K... Closed
related to SERVER-7155 Problem with authentication of connec... Closed

 Description   

If auth is turned on the connection being used is probably only authenticated against the input database and not the output database, so most likely writing the result of a map reduce to an output collection in a different database will fail.



 Comments   
Comment by Robert Stam [ 04/Apr/13 ]

In version 1.8 of the C# driver authentication is handled differently. Now all connections are authenticated against each one of the provided credentials.

To use map reduce with output to a collection in a different database simply provide credentials for both databases, and the connections will automatically be authenticated against both.

Alternatively, you could provide one credential for a single surrogate user (a new concept in server 2.4) and authorize that one user to read from the source database and to write to the destination database.

Comment by Robert Stam [ 27/Sep/12 ]

Linking to the corresponding SERVER ticket.

Comment by Robert Stam [ 27/Sep/12 ]

Not sure how or when we will address this issue, but as it turns out there is a very simple workaround available right now. The trick is to first call RequestStart on the output database (which results in the connection being authenticated for the output database) and then call MapReduce on the input collection within the scope of the Request (which results in the same connection also being authenticated for the input database).

Here's some working code illustrating the workaround:

var connectionString = "mongodb://localhost/?safe=true";
var server = MongoServer.Create(connectionString);
var inputDatabase = server.GetDatabase("inputdatabase", new MongoCredentials("user", "password"));
var inputCollection = inputDatabase.GetCollection("inputcollection");
 
// this is Example 1 on p. 87 of MongoDB: The Definitive Guide
// by Kristina Chodorow and Michael Dirolf
 
inputCollection.RemoveAll();
inputCollection.Insert(new BsonDocument { { "A", 1 }, { "B", 2 } });
inputCollection.Insert(new BsonDocument { { "B", 1 }, { "C", 2 } });
inputCollection.Insert(new BsonDocument { { "X", 1 }, { "B", 2 } });
 
var query = Query.Exists("B");
 
var map =
    "function() {\n" +
    "    for (var key in this) {\n" +
    "        emit(key, {count : 1});\n" +
    "    }\n" +
    "}\n";
 
var reduce =
    "function(key, emits) {\n" +
    "    total = 0;\n" +
    "    for (var i in emits) {\n" +
    "        total += emits[i].count;\n" +
    "    }\n" +
    "    return {count : total};\n" +
    "}\n";
 
var outputDatabase = server.GetDatabase("outputdatabase", new MongoCredentials("user", "password"));
using (outputDatabase.RequestStart())
{
    var options = MapReduceOptions.SetOutput(new MapReduceOutput { DatabaseName = "outputdatabase", CollectionName = "outputcollection" });
    var result = inputCollection.MapReduce(query, map, reduce, options);
}

Generated at Wed Feb 07 21:37:15 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.