Mongodb 不会使用游标检索具有 200 万条记录的集合中的所有文档

Anh*_*Thi 2 go mongodb mongo-go

我有 2,000,000 条记录的集合

> db.events.count();                                     ?
2000000             
Run Code Online (Sandbox Code Playgroud)

我使用 golang mongodb 客户端连接到数据库

> db.events.count();                                     ?
2000000             
Run Code Online (Sandbox Code Playgroud)

但是该程序仅检索大约 600,000 条记录,而不是每次我运行该程序时检索 2,000,000 条记录。

$ go run main.go
done
count = 605426
nErrors = 0
2020/09/18 11:23:43 End:         retrive db from mongo and publish to kafka took 10.080603336s
Run Code Online (Sandbox Code Playgroud)

我不知道为什么?我想检索所有 2,000,000 条记录。谢谢你的帮助。

icz*_*cza 5

您获取结果的循环可能会提前结束,因为您使用相同的ctx上下文来迭代具有 10 秒超时的结果。

这意味着如果检索和处理200万条记录(包括连接)需要10秒以上,上下文将被取消,因此游标也会报错。

请注意,设置FindOptions.NoCursorTimeouttrue只以防止闲置光标超时,而不会覆盖所使用的上下文的超时。

使用另一个上下文来执行查询并迭代结果,一个没有超时的上下文,例如context.Background().

另请注意,为了构造 的选项find,请使用辅助方法,因此它可能看起来像这样简单而优雅:

options.Find().SetBatchSize(10000).SetNoCursorTimeout(true)
Run Code Online (Sandbox Code Playgroud)

所以工作代码:

ctx2 := context.Background()

cur, err := collection.Find(ctx2, bson.D{},
    options.Find().SetBatchSize(10000).SetNoCursorTimeout(true))

// ...

for cur.Next(ctx2) {
    // ...
}

// Also check error after the loop:
if err := cur.Err(); err != nil {
    log.Printf("Iterating over results failed: %v", err)
}
Run Code Online (Sandbox Code Playgroud)