我收集了2,000,000条记录

> db.events.count();                                     │
2000000
我使用golang mongodb客户端连接到数据库
package main

import (
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27888").SetAuth(options.Credential{
        Username: "mongoadmin",
        Password: "secret",
    }))

    if err != nil {
        panic(err)
    }

    defer func() {
        if err = client.Disconnect(ctx); err != nil {
            panic(err)
        }
    }()


    collection := client.Database("test").Collection("events")

    var bs int32 = 10000
    var b = true
    cur, err := collection.Find(context.Background(), bson.D{}, &options.FindOptions{
        BatchSize: &bs, NoCursorTimeout: &b})
    if err != nil {
        log.Fatal(err)
    }
    defer cur.Close(ctx)

    s, n := runningtime("retrive db from mongo and publish to kafka")
    count := 0
    for cur.Next(ctx) {
        var result bson.M
        err := cur.Decode(&result)
        if err != nil {
            log.Fatal(err)
        }

        bytes, err := json.Marshal(result)
        if err != nil {
            log.Fatal(err)
        }
        count++

        msg := &sarama.ProducerMessage{
            Topic: "hello",
            // Key:   sarama.StringEncoder("aKey"),
            Value: sarama.ByteEncoder(bytes),
        }
        asyncProducer.Input() <- msg
    }


但是该程序仅检索约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
不知道为什么我想检索所有2,000,000条记录。谢谢你的帮助。

最佳答案

由于使用相同的ctx上下文来迭代具有10秒超时的结果,因此获取结果的循环可能会提前结束。
这意味着,如果检索和处理200万条记录(包括连接)花费的时间超过10秒,则上下文将被取消,因此光标还将报告错误。
请注意,将 FindOptions.NoCursorTimeout 设置为true只是为了防止光标因不 Activity 而超时,它不会覆盖使用的上下文的超时。
使用另一种上下文来执行查询并遍历结果,该上下文没有超时,例如 context.Background()
另请注意,要为find构造选项,请使用helper方法,因此它看起来像这样简单而优雅:

options.Find().SetBatchSize(10000).SetNoCursorTimeout(true)
所以工作代码:
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)
}

关于mongodb - Mongodb不会使用游标检索具有200万条记录的集合中的所有文档,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63950411/

10-15 09:24