Ctrl_Alt_Defeat
Ctrl_Alt_Defeat

Reputation: 4009

Aggregate function issue with latest version of MongoC# Driver

I have .NET Application that uses MongoDB. Current driver I am using is 1.9.2. I am trying to upgrade it to 2.7.0.

I am having some difficulty in getting an Aggregate query to work in the new version:

The working code in version 1.9.2 of the driver is:

    public IEnumerable<Car> GetCarsModifiedInPeriod(DateTimeOffset dateFrom, DateTimeOffset dateTo)
    {
        var matchRequestFromDate = new BsonDocument
        {
            {
                "$match",
                new BsonDocument
                {
                    {
                        // Filter out those too recently modified
                       "LastUpdatedOn.0", new BsonDocument {{"$gte", dateFrom.Ticks}}
                    }
                }
            }
        };
        var matchRequestToDate = new BsonDocument
        {
            {
                "$match",
                new BsonDocument
                {
                    {
                        // Filter out those too recently modified
                        "LastUpdatedOn.0", new BsonDocument {{"$lte", dateTo.Ticks}}
                    }
                }
            }
        };

        var cars = collection.Aggregate(new AggregateArgs
        {
            Pipeline = new[] { matchRequestFromDate, matchRequestToDate},              
            AllowDiskUse = true,
            // Setting the OutputMode to Cursor allows us to return Mongo Doc Size > 16 MB - in the case when a large date  
            // range is used or a large number of cars were modified in a short period of time
            OutputMode = AggregateOutputMode.Cursor
        }).Select(r => r.Values.Select(c => c.AsObjectId.ToString()).First());

        var returnData = collection.AsQueryable().Where(c => cars.Contains(c.Id)).Select(c => c);

        return returnData;
    }

With a breakpoint set on returnData for the two periods specified I am getting a count of 25 cars which is what I expect.

This is how I have attempted to re-write for 2.7.0 version of driver:

    public IEnumerable<Car> GetCarsModifiedInPeriod(DateTimeOffset dateFrom, DateTimeOffset dateTo)
    {
        var matchRequestFromDate = new BsonDocument
        {
            {
                "$match",
                new BsonDocument
                {
                    {
                        // Filter out those too recently modified
                       "LastUpdatedOn.0", new BsonDocument {{"$gte", dateFrom.Ticks}}
                    }
                }
            }
        };
        var matchRequestToDate = new BsonDocument
        {
            {
                "$match",
                new BsonDocument
                {
                    {
                        // Filter out those too recently modified
                        "LastUpdatedOn.0", new BsonDocument {{"$lte", dateTo.Ticks}}
                    }
                }
            }
        };

        var pipeline = new[] {matchRequestFromDate, matchRequestToDate};
        //var mongoPipeline = new AggregateArgs { Pipeline = pipeline, AllowDiskUse = true, OutputMode = AggregateOutputMode.Cursor };

        var aggregate = collection.Aggregate(); //.Match(mongoPipeline);

        aggregate.Options.AllowDiskUse = true;
        aggregate.Options.UseCursor = true;

        foreach (var pipe in pipeline)
        {
            aggregate.AppendStage<BsonDocument>(pipe);
        }

        var returnData = aggregate.ToList();

        return returnData;  
    }

If I set a breakpoint in returnData in this method I am getting a count of around 10K cars so it doesnt look like I am correctly applying the same matches

Upvotes: 0

Views: 880

Answers (1)

rrrr-o
rrrr-o

Reputation: 2516

Is there a reason you are doing everything in BsonDocuments? There are methods that would make your life a lot easier, for example something like this.

collection.Aggregate(new AggregateOptions() { AllowDiskUse = true, UseCursor = true })
.Match(Builders<BsonDocument>.Filter.Gte("LastUpdatedOn.0", dateFrom.Ticks) & Builders<BsonDocument>.Filter.Lte("LastUpdatedOn.0", dateFrom.Ticks))
.ToListAsync()

You could tidy the filtering up more as well by using the right class for the collection and the builders.

Looking at the query, I'm not sure you even need to be using an aggregate unless you are doing more than a match. It could simply be a find.

Upvotes: 1

Related Questions