问题描述
我正在使用 C# MongoDB.Driver 2.12.4
MongoDB 一切都很好。不幸的是,我必须使用 AWS DocumentDB 作为生产数据库,它声称与 MongoDB 兼容,但我一直在发现几个问题:
- 索引有限https://docs.aws.amazon.com/documentdb/latest/developerguide/mongo-apis.html#mongo-apis-index
- 不支持排序索引或查询(已删除,设法通过其他方式进行不区分大小写的搜索)
- 它不支持 facet(我用它来高效分页)
"message": "Command aggregate Failed: Aggregation stage not supported: '$facet'.",
问题是:使用 AWS DocumentDB 对结果进行分页的最佳方法是什么?是否有任何选项可以通过单个查询做到这一点?或者我必须两次访问数据库?
这是我使用 Facet 和聚合 facet 结果的原始实现。
public async Task<PagedResult<TDocument>> GetAll<TDocument>(
Expression<Func<TDocument,bool>> filter,Sort<TDocument> sort,Pagination pagination,CancellationToken cancellationToken = new())
where TDocument : class,IDocument
{
filter ??= doc => true;
sort ??= Sort<TDocument>.Default;
if (pagination == null) throw new ArgumentNullException(nameof(pagination));
var collection = _collectionRetrieverService.GetCollection<TDocument>();
var sortDeFinition = GetSortDeFinition(sort);
var pageNumber = pagination.PageNumber;
var pageSize = pagination.PageSize;
var countPipelineDeFinition =
PipelineDeFinition<TDocument,AggregateCountResult>
.Create(new[]
{
PipelinestageDeFinitionBuilder.Count<TDocument>()
});
var dataPipelineDeFinition =
PipelineDeFinition<TDocument,TDocument>
.Create(new[]
{
PipelinestageDeFinitionBuilder.sort(sortDeFinition),PipelinestageDeFinitionBuilder.Skip<TDocument>((pageNumber -1) * pageSize),PipelinestageDeFinitionBuilder.Limit<TDocument>(pageSize)
});
const string countFacetName = "count";
const string dataFacetName = "data";
var countFacet = AggregateFacet.Create(countFacetName,countPipelineDeFinition);
var dataFacet = AggregateFacet.Create(dataFacetName,dataPipelineDeFinition);
var aggregateOptions =
new AggregateOptions
{
// Collation is not currently supported in AWS DocumentDB. See https://docs.aws.amazon.com/documentdb/latest/developerguide/mongo-apis.html#mongo-apis-index
//Collation = Collationoptions.CaseInsensitiveCollation
};
var aggregation =
await collection
.Aggregate(aggregateOptions)
.Match(filter)
.Facet(countFacet,dataFacet)
.ToListAsync(cancellationToken);
var count =
aggregation
.First()
.Facets
.First(x => x.Name == countFacetName)
.Output<AggregateCountResult>()
?.FirstOrDefault()
?.Count;
if (count is null)
{
var emptyResult =
new PagedResult<TDocument>()
{
Items = Enumerable.Empty<TDocument>(),PageNumber = pageNumber,PageSize = pageSize,TotalPages = pageNumber,TotalCount = 0
};
return emptyResult;
}
var totalPages = (int)Math.Ceiling((double)count/ pageSize);
var data =
aggregation
.First()
.Facets
.First(x => x.Name == dataFacetName)
.Output<TDocument>();
var result =
new PagedResult<TDocument>
{
Items = data,TotalPages = totalPages,TotalCount = count.Value
};
return result;
}
更新 2021-07-06
这是我的解决方法,它查询了两次数据库,因为我需要匹配过滤条件的项目总数。
public async Task<PagedResult<TDocument>> GetAll<TDocument>(
Expression<Func<TDocument,IDocument
{
filter ??= doc => true;
sort ??= Sort<TDocument>.Default;
if (pagination == null) throw new ArgumentNullException(nameof(pagination));
var collection = _collectionRetrieverService.GetCollection<TDocument>();
var sortDeFinition = GetSortDeFinition(sort);
var pageNumber = pagination.PageNumber;
var pageSize = pagination.PageSize;
var skipCount = pageSize * (pageNumber - 1);
var count = await collection.CountDocumentsAsync(filter,cancellationToken: cancellationToken);
if (count == 0)
{
var emptyResult =
new PagedResult<TDocument>()
{
Items = Enumerable.Empty<TDocument>(),TotalCount = count
};
return emptyResult;
}
var totalPages = (int)Math.Ceiling((double)count/ pageSize);
var findOptions =
new FindOptions<TDocument,TDocument>
{
AllowPartialResults = false,Sort = sortDeFinition,Limit = pageSize,Skip = skipCount
// Collation is not currently supported in AWS DocumentDB. See https://docs.aws.amazon.com/documentdb/latest/developerguide/mongo-apis.html#mongo-apis-index
//Collation = Collationoptions.CaseInsensitiveCollation
};
var queryResult = await collection.FindAsync(filter,findOptions,cancellationToken);
var results = await queryResult.ToListAsync(cancellationToken: cancellationToken);
var result =
new PagedResult<TDocument>
{
Items = results,TotalCount = count
};
return result;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)