MGO TTL索引的创建以选择性删除文档。

huangapple go评论90阅读模式
英文:

MGO TTL indexes creation to selectively delete documents

问题

我正在使用Golang和MongoDB进行工作。我有一个集合,需要保留一个可以持久或易失的文档。因此,如果设置了过期日期(例如expireAt),则认为该文档是易失的,并且会被删除;否则,它将保留在集合中,除非手动删除。

阅读这个文档,我发现了一个可能符合我的需求的索引。

基本上,我需要在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!"
} )

我读过(我正在寻找这些信息的来源)如果expireAt不是一个有效的日期,删除操作将不会触发。因此,我认为我所需要做的就是在需要时将expireDate设置为有效的日期,否则我将将其设置为Go的time.Time零值。

这是我的代码:

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

// 从通过REST API接收到的数据创建过滤器。
var filter Filter
timestamp := time.Now()

if theUserAction == "share" { // 这个操作将把文档设置为易失的
    filter.ExpireAt = time.Now().Add(24 * time.Hour * 14)
}

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

// 将过滤器存储在数据库中
session, err := mdb.GetMgoSession() // 这是一个返回有效mgo会话的封装方法
if err != nil {
    return NewErrorInternal("连接数据库时出错", err)
}
defer session.Close()

// 获取全局数据的数据库
collection := session.DB(database).C(filtersCollection)

我的问题是:我如何设置索引,以便在expireAt键有效时删除文档?
阅读mgo关于索引类型的文档,似乎没有办法复制先前提到的索引,因为该库只提供了ExpireAfter字段。

另外,可以假设零值被MongoDB解释为无效日期吗?

从文档中可以看出,它是公元1年1月1日00:00:00.000000000 UTC,实际上看起来是一个有效的日期。

到目前为止,我考虑的解决方案是这样的:

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

希望对你有帮助!

英文:

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

得分: 4

如何设置索引以便在expireAt键有效时删除文档?

使用mgo.v2设置TTL索引的示例代码如下:

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

上述示例将文档的过期时间设置为120秒。更多信息请参考通过设置TTL来使集合中的数据过期

是否仍然可以使某些文档永不过期?因为我希望在一个集合中,某些文档过期而其他文档保持永久。

您可以为ExpireAt结构字段指定omitempty标志,示例如下:

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

这样只有在字段不为零值时才包含该字段。更多信息请参考mgo.v2 bson.Marshal

例如,您可以插入两个文档,其中一个会过期,另一个会保持永久。代码示例:

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)

稍后,您可以使用Update()方法设置expireAt字段,示例如下:

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

expireAt字段设置有效的时间值将使其符合TTL索引的条件,即不再保持永久。

根据您的用例,您还可以选择使用Remove()方法删除文档,而不是更新并依赖TTL索引。

英文:

> 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.

huangapple
  • 本文由 发表于 2016年4月19日 22:00:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/36720669.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定