Mongo TTL没有删除文件

时间:2016-01-15 02:01:01

标签: mongodb

我正在使用集合中的自动过期文档。 java应用程序根据Mongo TTL文档创建索引。

coll.createIndex(new Document("Expires", 1).append("expireAfterSeconds", 0));

插入文档时,我将Expires字段设置为将来Date。对于这个测试,我将来会将它设置为1分钟。

我已经验证了日期是否存在正确,索引似乎是正确的,而且我已经等了10多分钟(即使ttl跑步者每隔60秒运行一次)但文档仍然存在。

{
    "_id" : ObjectId("569847baf7794c44b8f2f17b"),
    // my data
    "Created" : ISODate("2016-01-15T02:02:30.116Z"),
    "Expires" : ISODate("2016-01-15T02:03:30.922Z")
}

我还能错过什么?以下是索引:

[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "prism.prismEventRecord"
    },
    {
        "v" : 1,
        "key" : {
            "Location.X" : 1,
            "Location.Z" : 1,
            "Location.Y" : 1,
            "Created" : -1
        },
        "name" : "Location.X_1_Location.Z_1_Location.Y_1_Created_-1",
        "ns" : "prism.prismEventRecord"
    },
    {
        "v" : 1,
        "key" : {
            "Created" : -1,
            "EventName" : 1
        },
        "name" : "Created_-1_EventName_1",
        "ns" : "prism.prismEventRecord"
    },
    {
        "v" : 1,
        "key" : {
            "Expires" : 1,
            "expireAfterSeconds" : 0
        },
        "name" : "Expires_1_expireAfterSeconds_0",
        "ns" : "prism.prismEventRecord"
    }
]

2 个答案:

答案 0 :(得分:1)

我想知道将java mongo客户端从图片中取出一分钟是否有意义。

我创建了一个类似的集合,并在shell中进行了以下调用。

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

当我这样做,然后我调用db.weblog.getIndexes()时,这就是过期索引的样子:

{
    "v" : 1,
    "key" : {
        "expireAt" : 1
    },
    "name" : "expireAt_1",
    "ns" : "logs.weblog",
    "expireAfterSeconds" : 0
}

我认为你的java调用可能是"追加"索引的新列(不设置您希望设置的属性)。看一下......您的索引def看起来像这样:

{
    "v" : 1,
    "key" : {
        "Expires" : 1,
        "expireAfterSeconds" : 0
    },
    "name" : "Expires_1_expireAfterSeconds_0",
    "ns" : "prism.prismEventRecord"
}

明白我的意思? " expireAfterSeconds是一个键,而不是属性。现在 - 你如何使用java shell?嗯...不要对我大喊大叫,但我是一个c#家伙...我发现了一两个punt on the question of ttl indexes from the java client的帖子,但他们已经老了。

也许java客户端变得更好,现在支持选项?希望知道问题是什么给了一个具有足够强大编码技能的人,可以从这里拿走它; - )

编辑:堆栈java驱动程序代码(未经测试):

IndexOptions options = new IndexOptions()
    .name('whocareswhatwecallthisindex')
    .expireAfter(1, TimeUnit.DAYS);
coll.createIndex(new Document("Expires", 1), options);

EDIT2:用于创建相同索引的C#驱动程序代码:

var optionsIdx = new CreateIndexOptions() { ExpireAfter = new TimeSpan(0)};
await coll.Indexes.CreateOneAsync(Builders<MyObject>.IndexKeys.Ascending("expiresAt"), optionsIdx);

答案 1 :(得分:0)

如果您以Golang用户身份遇到此问题,则有两种选择:

1使用结构:当您知道有效载荷结构时,该结构有效,并且有大量文献记录

2在JSON有效负载中引入实际的日期对象:仅在由于某种原因而由于某种原因绝对无法提前知道您的有效负载结构时才使用此对象。

就我而言,源数据来自结构为黑匣子的系统。我首先尝试引入一个符合ISO的TTL索引,其格式与Mongo的格式匹配,但仍被读取为文本。这导致我推断这是由于未指示驱动程序正确格式化它。

我相信深入研究Mongo Golang驱动程序的细节以操纵此过程只会给我们一个短暂的解决方案(因为实现细节可能会发生变化)。因此,相反,我建议在您的有效负载中引入一个实际的日期属性,并让驱动程序将其修改为适用于Mongo(此代码段中的原理适应您自己的代码结构)

err = json.Unmarshal([]byte (objectJsonString.String()), &objectJson)
if err == nil && objectJson != nil {
        //Must introduce as native or they are considered text
        objectJson["createdAt"] = time.Now()
        //Your other code
        insertResult, err := collection.InsertOne(context.TODO(), objectJson)
}

因此,基本上,通常使用其余数据创建JSON或BSON对象,然后使用实际日期值引入TTL索引,而不是尝试让JSON解析器为您工作。

我期盼着改正,请保持礼貌,我将确保通过任何观察来更新和完善此答案。