在golang中使用mongo,在指定的秒数后使文档过期?

yay*_*you 3 go ttl mongodb mongo-go

我正在尝试使用mongo-go-driver进行一些简单的操作。我在集合中插入一些数据,我希望它们在几秒钟后自动删除。

我已阅读以下文档:https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-after-a-specified-number-of-seconds

然后我在GO中写了一些东西,但它似乎没有按照我的预期工作。也许有些东西我没有得到,或者我做错了。

package main

import (
    "bytes"
    "context"
    "fmt"
    "log"
    "text/tabwriter"
    "time"

    "github.com/Pallinder/go-randomdata"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
    ctx := context.TODO()

    client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        log.Fatal(err)
    }
    err = client.Connect(ctx)
    if err != nil {
        log.Fatal(err)
    }

    db := client.Database("LADB")
    col := db.Collection("LACOLL")

    // add index to col
    // the goal is to set a TTL for datas to only 1 secondes (test purpose)
    model := mongo.IndexModel{
        Keys:    bson.M{"createdAt": 1},
        Options: options.Index().SetExpireAfterSeconds(1),
    }
    ind, err := col.Indexes().CreateOne(ctx, model)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(ind)

    // insert some datas each seconds
    for i := 0; i < 5; i++ {
        name := randomdata.SillyName()
        res, err := col.InsertOne(ctx, NFT{Timestamp: time.Now(), CreatedAt: time.Now(), Name: name})
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Inserted", name, "with id", res.InsertedID)
        time.Sleep(1 * time.Second)
    }

    // display all
    cursor, err := col.Find(ctx, bson.M{}, nil)
    if err != nil {
        log.Fatal(err)
    }
    var datas []NFT
    if err = cursor.All(ctx, &datas); err != nil {
        log.Fatal(err)
    }

    // I expect some datas not to be there (less than 5)
    fmt.Println(datas)
}

type NFT struct {
    ID        primitive.ObjectID `bson:"_id,omitempty"`
    CreatedAt time.Time          `bson:"createdAt,omitempty"`
    Timestamp time.Time          `bson:"timestamp,omitempty"`
    Name      string             `bson:"name,omitempty"`
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

你的例子没有任何问题,它有效。

请注意,expireAfterSeconds您指定的是文档过期后的持续时间createdAt,该时刻是可以删除文档的最早时间,但不能保证删除会“立即”发生,恰好在那个时间。

引用MongoDB 文档:TTL索引:删除操作的计时:

TTL索引并不保证过期数据会在过期后立即删除。文档过期时间和 MongoDB 从数据库中删除文档的时间之间可能存在延迟。

删除过期文档的后台任务每 60 秒运行一次。因此,在文档过期和后台任务运行之间的时间段内,文档可能会保留在集合中。

由于删除操作的持续时间取决于mongod实例的工作负载,因此过期数据可能会在后台任务运行之间的 60 秒时间段之外存在一段时间。

如您所见,如果文档过期,在最坏的情况下,后台任务可能需要 60 秒才能启动并开始删除过期文档,如果文档较多(或者数据库负载较重),则可能需要一些时间是时候删除所有过期的文档了。