[CSHARP-383] Aggregate Support Created: 17/Jan/12  Updated: 05/Apr/19  Resolved: 27/Jan/12

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

Type: Task Priority: Major - P3
Reporter: Chris Harris Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: question
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Is there a version of the C# driver that support the aggregate functionality in the server nightly build?



 Comments   
Comment by Craig Wilson [ 01/Feb/13 ]

CSHARP-601 is the tracking for Linq to Aggregation. It is likely destined for our 2.0 release.

Comment by Francis West [ 01/Feb/13 ]

Is there any time-frame or work in progress for this yet?

Comment by Mikael Koskinen [ 10/Oct/12 ]

Here's a tutorial which shows examples of using the MongoDB Aggregation Framework with C#.

Comment by Edward Wohlman [ 03/Apr/12 ]

Wow, that was quick.
I did a bit of an experiment to see compare the methods.

If Linq worked with the aggregate framework

var collection = db.GetCollection<AdministrativeArea>("AdminAreas");
var query = from aa in collection.AsQueryable<AdministrativeArea>()
where aa.Districts.Any()
from district in aa.Districts
where district.Name.StartsWith("L")
select district;

(currently throws a NotSupportedException about the 'SelectMany()' call)

vs the long way around using an explicit command.

var command = new CommandDocument
{

{ "aggregate", "AdminAreas" }

,
{ "pipeline", new BsonArray{
new BsonDocument{
{"$match", new BsonDocument{ {"Districts", new BsonDocument{

{"$exists",true}

}}}}
},
new BsonDocument{
{"$project", new BsonDocument{

{"row", "$Districts" }

} }
},
new BsonDocument{

{"$unwind", "$row" }

},
new BsonDocument{
{"$match", new BsonDocument{

{"row.Name", new BsonRegularExpression("^L") }

}}
},
} }
};

var districts = db.RunCommandAs<AggregateResult<District>>(command).Result;

with a little helper class to deserialize the unwound districts.

class AggregateResult<T> : CommandResult
{
public IEnumerable<T> Result
{
get

{ var resultArray = this.Response["result"].AsBsonArray.Select(row => row.AsBsonDocument); var rows = resultArray.Select(item => item["row"].AsBsonDocument); var objects = rows.Select(row => BsonSerializer.Deserialize<T>(row)); return objects; }

}
}

presuming the field is renamed to 'row'.

Comment by Robert Stam [ 03/Apr/12 ]

The LINQ implementation in the 1.4 version of the C# driver does not use the aggregation framework.

We also have realized that some LINQ queries would map well to aggregation framework pipelines, and we plan to research doing that and hope to have it in a future release.

Comment by Edward Wohlman [ 03/Apr/12 ]

Seems like the features of the Aggregation framework would map very nicely onto the standard
Linq operators.

$project => Select()
$limit => Take()
$group => GroupBy()
$sort => OrderBy(),OrderByDescending()
$unwind => SelectMany()
$skip => Skip()
$match => Where()

And Linq is ideally suited to building up a pipeline of operations
to submit to the server as a single command.

Does the new Linq capable version of the CSharp driver go as far
converting the expression tree into an aggregation pipeline or does
it only translate Linq expressions into the standard find() query builder
and cursor options?

I'll admit its probably pretty tricky getting it to work with
arbitrary Linq expressions with 'let' bindings etc.

You'd also have to automatically extract the returned structure
from the 'result' array as an IEnumerable of projected values,
but that part seems pretty straight forward.

Seems like an interesting thing to attempt anyway.

Comment by Robert Stam [ 17/Jan/12 ]

If by aggregate functionality you mean the new aggregation framework then keep in mind that any driver can run any command (whether it has a helper method or not) by building the command object and running it. Since the aggregation framework is command based it is simply a matter of building up the corresponding command and running it.

So for example:

var command = new CommandDocument
{
    { "aggregate", "article" },
    { "pipeline", new BsonArray
        { new BsonDocument { "$unwind", "tags" } }
    }
};
var result = database.RunCommand(command);

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