You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MongoDB C# Driver v2.17.1遍历文档时遇MongoCursorNotFoundException求助

解决方案:MongoDB C# Driver 游标找不到异常(MongoCursorNotFoundException)

问题原因

你的代码使用AsQueryable()遍历文档,单次迭代耗时2-5秒,处理1400条文档的累计时间远超MongoDB服务器默认游标超时时间(10分钟)。服务器会自动销毁闲置超时的游标,当程序尝试获取下一批数据时,就会抛出游标找不到的异常。


具体解决方案

1. 延长游标超时时间

通过FindOptions设置更长的游标超时时间,或临时禁用游标超时(注意用完必须释放游标):

string connectionString = @"mongodb://localhost:27017/";
var dbClient = new MongoClient(connectionString);
var db_sample = dbClient.GetDatabase("mongodbname");
var collection = db_sample.GetCollection<DataModel>("mongodbcollectionname");

// 设置游标超时为2小时(根据你的处理总时长调整)
var options = new FindOptions<DataModel>
{
    MaxTime = TimeSpan.FromHours(2)
};

// 或者禁用游标超时(不推荐长期使用,需确保游标被释放)
// options.NoCursorTimeout = true;

using (var cursor = collection.Find(Builders<DataModel>.Filter.Empty, options))
{
    while (cursor.MoveNext())
    {
        foreach (var cdm in cursor.Current)
        {
            // 文档处理与更新逻辑
        }
    }
}

2. 批量拉取+批量更新

减少游标闲置时间,每次拉取一批文档,批量处理后批量更新,大幅缩短总耗时:

int batchSize = 500; // 可根据内存调整批次大小
var filter = Builders<DataModel>.Filter.Empty;
var cursor = collection.Find(filter).BatchSize(batchSize);

while (cursor.MoveNext())
{
    var batch = cursor.Current.ToList();
    var updateBatch = new List<UpdateOneModel<DataModel>>();

    foreach (var cdm in batch)
    {
        // 生成更新操作
        var update = Builders<DataModel>.Update
            .Set(x => x.TargetField, UpdatedValue) // 替换为你的更新逻辑
            .Set(x => x.AnotherField, AnotherValue);
        
        updateBatch.Add(new UpdateOneModel<DataModel>(
            Builders<DataModel>.Filter.Eq(x => x.Id, cdm.Id),
            update
        ));
    }

    // 批量提交更新
    if (updateBatch.Count > 0)
    {
        collection.BulkWrite(updateBatch);
    }
}

3. 改用异步遍历提升效率

异步操作避免阻塞,减少游标等待时间,同时利用MongoDB驱动的异步优化:

await collection.Find(Builders<DataModel>.Filter.Empty)
    .ForEachAsync(async cdm =>
    {
        // 异步处理与更新
        var update = Builders<DataModel>.Update.Set(x => x.TargetField, UpdatedValue);
        await collection.UpdateOneAsync(Builders<DataModel>.Filter.Eq(x => x.Id, cdm.Id), update);
    });

4. 优化单条文档处理逻辑(根本解决)

将单次迭代耗时从2-5秒降低,从根源避免游标超时:

  • 缓存循环内重复查询的数据(如关联表数据)
  • 减少不必要的IO操作(文件读写、网络请求等)
  • 优化计算逻辑,必要时采用并行处理(注意线程安全)
  • 避免在循环内创建不必要的对象或重复初始化资源

内容的提问来源于stack exchange,提问作者bharathN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:55:36