C#中MongoDB查询优化咨询:现有FluentResults实现如何改进?
优化方案分析
你的代码存在一个明显的性能问题:对数据库发起了两次查询——先调用AnyAsync判断是否存在文档,再调用FirstAsync获取具体文档,这会增加数据库往返次数,放大延迟和资源消耗。下面是几个关键优化点和最终实现:
核心优化点
- 合并数据库请求:用一次查询完成“存在性检查+获取目标字段”的操作,避免两次网络往返。
- 处理Result的失败状态:原代码直接访问
collection.Value,如果传入的Result<IMongoCollection<T>>本身是失败状态,会抛出异常,需要先判断状态。 - 投影优化:只查询需要的
StreamId字段,而非整个文档,减少数据传输量。
优化后的代码
public static async Task<Result<ObjectId>> GetExistingStreamIdAsync<T>( this Result<IMongoCollection<T>> collection, Expression<Func<T, bool>> filter) where T : IHasName, IHasVersionId, IHasStreamId { // 先处理collection本身的失败情况 if (collection.IsFailed) return Result.Fail<ObjectId>(collection.Errors); // 只投影StreamId,一次查询完成判断和取值 var streamId = await collection.Value .Find(filter) .Project(x => x.StreamId) .FirstOrDefaultAsync(); return streamId != default(ObjectId) ? Result.Ok(streamId) : Result.Fail<ObjectId>($"No document exists for filter = '{filter}'"); }
额外说明
- 使用
FirstOrDefaultAsync可以直接返回匹配的第一个StreamId,如果没有匹配结果则返回ObjectId的默认值(空值),以此替代两次查询。 - 投影操作
Project(x => x.StreamId)让MongoDB只返回StreamId字段,相比返回整个文档,能显著减少网络传输的数据量,尤其是在文档结构复杂时效果更明显。 - 增加了对
collection.IsFailed的判断,确保当传入的集合Result失败时,能正确传递错误信息,避免运行时异常。
内容的提问来源于stack exchange,提问作者Thor
相关产品推荐
相关产品推荐

