Následující kód jsem od někud ukradl a trochu modifikoval. Jedná se o extension metodu, kterou lze zavolat nad IMongoCollection<TDocument>
a vrátí to výsledek typu ListResult<TDocument>
(jeho definice je níže) který obsahuje:
- data
- celkový počet dokumentů (
estimatedDocumentCount
má rychlost O(1)) - filtrovaný počet dokumentů
- počet stránek
Nepodařilo se mi ale zjistit, jak sloučit ten estimatedDocumentCount
s tím agregovaným výstupem. V tuto chvíli tato extension metoda volá MongoDB 2x: nejdřív to vrátí agregovaný výstup skrz aggregate a pak se k tomu připojí ten estimatedDocumentCount
. Líbilo by se mi, kdyby to bylo jen 1 volání ale nepřišel jsem na to, jak ten estimatedDocumentCount
do toho aggregate výstupu dostat.
public static async Task<ListResult<TDocument>> ListResultAsync<TDocument>(
this IMongoCollection<TDocument> collection,
int pageIndex = 0,
int pageSize = 10,
FilterDefinition<TDocument> filterDefinition = null,
SortDefinition<TDocument> sortDefinition = null)
{
var countFacet = AggregateFacet.Create("count",
PipelineDefinition<TDocument, AggregateCountResult>.Create(new[]
{
PipelineStageDefinitionBuilder.Count<TDocument>()
}));
var stages = new List<PipelineStageDefinition<TDocument, TDocument>>();
if (sortDefinition != null)
stages.Add(PipelineStageDefinitionBuilder.Sort(sortDefinition));
stages.AddRange(new[]
{
PipelineStageDefinitionBuilder.Skip<TDocument>(pageIndex * pageSize),
PipelineStageDefinitionBuilder.Limit<TDocument>(pageSize)
});
var dataFacet = AggregateFacet.Create("data", PipelineDefinition<TDocument, TDocument>.Create(stages));
var aggregationQuery = collection.Aggregate();
if (filterDefinition != null)
aggregationQuery = aggregationQuery.Match(filterDefinition);
var aggregation = await aggregationQuery.Facet(countFacet, dataFacet).ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "count")
.Output<AggregateCountResult>()
.FirstOrDefault()
.Count;
var data = aggregation.First()
.Facets.First(x => x.Name == "data")
.Output<TDocument>();
return new ListResult<TDocument>
{
Data = data,
TotalRowsUnfiltered = await collection.EstimatedDocumentCountAsync(),
TotalPagesFiltered = (int)Math.Ceiling((double)count / pageSize),
TotalRowsFiltered = count
};
}
A zde je ten ListResult<TDocument>
public class ListResult<T>
{
public long TotalRowsUnfiltered { get; set; }
public long TotalRowsFiltered { get; set; }
public int TotalPagesFiltered { get; set; }
public IEnumerable<T> Data { get; set; }
}