我使用的是用于C#的2.2版MongoDB驱动程序。 我想分页查询:对查询的响应必须包含当前页面的项目以及与查询匹配的项目总数。
我想做一个查询。 使用mongo shell我可以意识到:
var c = db.mycol.find({....}).skip(0).limit(10)
var total = c.count();
while (c.hasNext()) {
print(tojson(c.next()));
}
但是使用C#驱动程序,我不知道如何只使用一个查询。
var find = collection
.Find(x => x.Valid == true)
.Skip(0)
.Limit(10);
var cursor = await find.ToCursorAsync(cancellationToken);
// How to get the count? There is no method in the IAsyncCursor interface.
有可能吗?一些想法?
答案 0 :(得分:7)
您只能通过向DB发送一个查询来完成任务。通常的做法是遵循
var query = GetCollection().Find(x => x.Valid == true);
var totalTask = query.CountAsync();
var itemsTask = query.Skip(0).Limit(10).ToListAsync();
await Task.WhenAll(totalTask, itemsTask);
return new Page{ Total = totalTask.Result, Items = itemsTask.Result};
答案 1 :(得分:0)
在 MongoDB 中,我们能够创建一个数据处理管道,该管道将对我们的数据执行一次。
public class Person
{
[BsonId]
[BsonRepresentation(BsonType.String)]
public string Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
}
public class Peger
{
public int Count { get; set; }
public int Page { get; set; }
public int Size { get; set; }
public IEnumerable<Person> Items { get; set; }
}
class Program
{
static async Task Main(string[] args)
{
var client = new MongoClient();
var database = client.GetDatabase("pager_test");
var collection = database.GetCollection<Person>(nameof(Person));
int page = 1;
int pageSize = 5;
var results = await GetPagerResultAsync(page, pageSize, collection);
}
private static async Task<Peger> GetPagerResultAsync(int page, int pageSize, IMongoCollection<Person> collection)
{
// count facet, aggregation stage of count
var countFacet = AggregateFacet.Create("countFacet",
PipelineDefinition<Person, AggregateCountResult>.Create(new[]
{
PipelineStageDefinitionBuilder.Count<Person>()
}));
// data facet, we’ll use this to sort the data and do the skip and limiting of the results for the paging.
var dataFacet = AggregateFacet.Create("dataFacet",
PipelineDefinition<Person, Person>.Create(new[]
{
PipelineStageDefinitionBuilder.Sort(Builders<Person>.Sort.Ascending(x => x.Surname)),
PipelineStageDefinitionBuilder.Skip<Person>((page - 1) * pageSize),
PipelineStageDefinitionBuilder.Limit<Person>(pageSize),
}));
var filter = Builders<Person>.Filter.Empty;
var aggregation = await collection.Aggregate()
.Match(filter)
.Facet(countFacet, dataFacet)
.ToListAsync();
var count = aggregation.First()
.Facets.First(x => x.Name == "countFacet")
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count ?? 0;
var data = aggregation.First()
.Facets.First(x => x.Name == "dataFacet")
.Output<Person>();
return new Pager
{
Count = (int)count / pageSize,
Size = pageSize,
Page = page,
Items = data
};
}
}