【发布时间】:2019-03-13 21:02:39
【问题描述】:
有关背景信息,请参阅以下帖子:MongoDB C# Driver - Return last modified rows only
在运行此代码近两年后,我们最近一直遇到性能问题,尽管我一直在说代码不是问题,但基础架构坚持认为这是因为我正在执行全表扫描。
问题是特定于环境的问题。我们的 QA 环境一直像梦一样运行,但 Dev 和 Prod 有时很慢,有时却很好——非常不稳定。他们有相同的数据和代码,但 Dev 和 Prod 有另一个也在数据库上运行的应用程序。
我的数据有一个 Id 和一个 _id(或 AuditId) - 我按 Id 对数据进行分组,然后返回该记录的最后一个 _id,它没有被删除。我们有多个相同 ID 的历史记录,我想退回最后一个(请参阅原始帖子)。
所以我有以下方法:
private static FilterDefinition<T> ForLastAuditIds<T>(IMongoCollection<T> collection) where T : Auditable, IMongoAuditable
{
var pipeline = new[] { new BsonDocument { { "$group", new BsonDocument { { "_id", "$Id" }, { "LastAuditId", new BsonDocument { { "$max", "$_id" } } } } } } };
var lastAuditIds = collection.Aggregate<Audit>(pipeline).ToListAsync().Result.ToList().Select(_ => _.LastAuditId);
var forLastAuditIds = Builders<T>.Filter.Where(_ => lastAuditIds.Contains(_.AuditId) && _.Status != "DELETE");
return forLastAuditIds;
}
这个方法由下面的方法调用,它接受一个表达式,它附加到由 ForLastAuditIds 创建的 FilterDefinition。
protected List<T> GetLatest<T>(IMongoCollection<T> collection,
Expression<Func<T, bool>> filter, ProjectionDefinition<T, T> projection = null,
bool disableRoleCheck = false) where T : Auditable, IMongoAuditable
{
var forLastAuditIds = ForLastAuditIds(collection);
var limitedList = (
projection != null
? collection.Find(forLastAuditIds & filter, new FindOptions()).Project(projection)
: collection.Find(forLastAuditIds & filter, new FindOptions())
).ToListAsync().Result.ToList();
return limitedList;
}
现在,所有这些工作都非常好,并且被我所有调用 Collections 的代码重复使用,但是这个特定的集合比其他集合要大得多,而且我们正在减慢那个集合。
我的问题是:有没有办法让我获取聚合和过滤器生成器并将它们组合起来以返回一个过滤器定义,我可以在不先运行全表扫描的情况下使用它?
我真的希望我说得通。
【问题讨论】:
标签: c# mongodb aggregation