'MongoDB: AggregateCountResult always returns 0

I've found this great blog post: https://kevsoft.net/2020/01/27/paging-data-in-mongodb-with-csharp.html

Based on it, I created a following extension method:

public static async Task<PaginatedResults<TLink>> RetrieveLinksPaginatedAsync<TLink>(this IMongoCollection<TLink> collection, Guid? userID, int start, int? count, bool sortAscending = true, CancellationToken cancellationToken = default) where TLink : class, IRedirectableLink
{
    const string countFacetName = "count";
    const string dataFacetName = "data";

    // filter for specific user
    FilterDefinition<TLink> filter = userID != null
        ? Builders<TLink>.Filter.Eq(link => link.UserID, userID)
        : Builders<TLink>.Filter.Empty;

    // facet for total count of collection
    AggregateFacet<TLink, AggregateCountResult> countFacet = AggregateFacet.Create(countFacetName,
        PipelineDefinition<TLink, AggregateCountResult>.Create(new IPipelineStageDefinition[]
        {
            PipelineStageDefinitionBuilder.Count<TLink>()
        }));

    // build facet for paging
    // sort is based on sortAscending
    // if start 0, don't add skipping
    // if count null, don't add limiting
    List<IPipelineStageDefinition> dataStages = new List<IPipelineStageDefinition>(3);
    dataStages.Add(PipelineStageDefinitionBuilder.Sort(sortAscending
        ? Builders<TLink>.Sort.Ascending(link => link.CreationTimeUTC)
        : Builders<TLink>.Sort.Descending(link => link.CreationTimeUTC)));
    if (start > 0)
        dataStages.Add(PipelineStageDefinitionBuilder.Skip<TLink>(start));
    if (count != null)
        dataStages.Add(PipelineStageDefinitionBuilder.Limit<TLink>(count.Value));
    AggregateFacet<TLink, TLink> dataFacet = AggregateFacet.Create(dataFacetName,
        PipelineDefinition<TLink, TLink>.Create(dataStages));

    // run aggregate pipeline
    IEnumerable<AggregateFacetResults> results = await collection.Aggregate()
        .Match(filter)
        .Facet(countFacet, dataFacet)
        .ToListAsync(cancellationToken).ConfigureAwait(false);

    IEnumerable<TLink> pageElements = results.FirstOrDefault()?.Facets.First(x => x.Name == dataFacetName).Output<TLink>() ?? Enumerable.Empty<TLink>();
    long totalCount = results.FirstOrDefault()?.Facets.First(x => x.Name == countFacetName).Output<AggregateCountResult>().FirstOrDefault()?.Count ?? 0;

    return new PaginatedResults<TLink>(pageElements, totalCount);
}

I run it against start = 0, count = 5. As expected, pageElements has 5 items. However totalCount equals 0 - and it's also 0 if I simply inspect results object, too, which eliminates the nulls issue.

When investigating, I determined that this also returns 0:

results = await collection.Aggregate()
    .Facet(countFacet)
    .ToListAsync(cancellationToken).ConfigureAwait(false);

While this returns 11:

totalCount = await collection.CountDocumentsAsync(filter);

To me it seems like it's the count facet specifically that doesn't work correctly. But I cannot figure out why.

For reference, I run the queries against MongoDB Atlas Free Tier, and use MongoDB.Driver package version 2.15.0.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source