dsj8000 2016-04-19 14:00
浏览 94
已采纳

创建MGO TTL索引以有选择地删除文档

I'm working with Golang and MongoDB. I have a collection which needs to keep a document which can be persistent or volatile. Hence, if it's set an expire date (as the example expireAt) the document is considered volatile and deleted otherwise it'll be kept in the collection unless it'll be manually deleted.

Reading this doc I've found an index that might work as I need it to.

Basically I need to replicate this kind of index in mgo:

db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

db.log_events.insert( {
  "expireAt": new Date('July 22, 2013 14:00:00'),
  "logEvent": 2,
  "logMessage": "Success!"
} )

I've read (I'm searching back for the source of this information) that if the expireAt is not a valid date the deletion won't be trigger. Thus I think that all I need to do is to set the expireDate to a valid date when I need it, otherwise I'll leave it to the Go time.Time zero value.

This is my codebase

type Filter struct {
    Timestamp time.Time     `bson:"createdAt"`
    ExpireAt  time.Time     `bson:"expireAt"`
    Body      string        `bson:"body"`
}

// Create filter from data received via REST API.
var filter Filter
timestamp := time.Now()

if theUserAction == "share" { // This is action will set the document as volatile
    filter.ExpireAt = time.Now().Add(24 * time.Hour * 14)
}

filter.Timestamp = timestamp
filter.Body = "A BODY"

// Store filter in database
session, err := mdb.GetMgoSession() // This is a wrapping method that returns a valid mgo session
if err != nil {
    return NewErrorInternal("Error connecting to database", err)
}
defer session.Close()


// Get db with global data for legent
collection := session.DB(database).C(filtersCollection)

My question is: how can I set the index thus that it'll delete the document IF the expireAt key is valid? Reading the mgo documentation about Index Type it doesn't seems like there's a way to replicate the previously stated index, since the library only provides the ExpireAfter field..

Also, it's valid to assume that a zerovalue could be interpreted by mongodb as an invalid date?

From the docs it is January 1, year 1, 00:00:00.000000000 UTC which actually seems like a valid date..

What I've thought so far is doing something like this:

filtIdx := mgo.Index{
    Key:        []string{"expireAt"},
    Unique:     false,
    Background: true,
    Sparse:     false,
    ExpireAfter: 0,
}
  • 写回答

1条回答 默认 最新

  • dpowt82802 2017-07-27 07:01
    关注

    How can I set the index thus that it'll delete the document IF the expireAt key is valid?

    An example to set a TTL index using mgo.v2 is as below:

    index := mgo.Index{
        Key:         []string{"expireAt"},
        ExpireAfter: time.Second * 120, 
    }
    err = coll.EnsureIndex(index)
    

    Where the above example sets to 120 seconds of expiration. See also Expire Data from Collections by Setting TTL.

    Is it still possible to make some documents to not expire at all? Since this is the behaviour I'm looking forward to obtain a collection where some documents do expire while other remain persistent

    You can specify omitempty flag for ExpireAt struct field as below:

    type Filter struct {
        Timestamp time.Time `bson:"createdAt"`
        Body      string    `bson:"body"`
        ExpireAt  time.Time `bson:"expireAt,omitempty"`
    }
    

    Which essentially only include the field if it's not set to a zero value. See more info mgo.v2 bson.Marshal

    Now, for example you can insert two documents where one would expire and the other persists. Code example:

    var foo Filter
    foo.Timestamp = timestamp
    foo.Body = "Will be deleted per TTL index"
    foo.ExpireAt = time.Now()
    collection.Insert(foo)
    
    var bar Filter
    bar.Timestamp = timestamp
    bar.Body = "Persists until expireAt value is set"
    collection.Insert(bar)
    

    Later on, you can set the expireAt field with an Update(), as an example:

    newValue := bson.M{"$set": bson.M{"expireAt": time.Now()}}
    err = collection.Update(queryFilter, newValue)
    

    Setting a valid time value for expireAt field, would make it qualify for the TTL index. i.e. no longer persists.

    Depending on your use case, alternatively you may as well Remove() the document instead of updating and relying on TTL index.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记