【问题标题】:Documents not expiring using TTL in mongodb 3.0 (.Net driver 2.0)在 mongodb 3.0(.Net 驱动程序 2.0)中使用 TTL 的文档不会过期
【发布时间】:2015-08-13 01:23:26
【问题描述】:

我有以下代码。构造函数调用 EnsureIndexes 以确保已在 _expireAt 字段上创建 TTL 索引。然后,当通过调用 AddOrUpdateItem 方法插入文档时,它会将未来日期添加到 _expireAt 字段。但是,该日期过去了,文档永不过期。我做错了什么?

private void EnsureIndexes()
    {
        if (!_indexChecked)
        {
            // TTL index
            var tsk = 
                MongoCollection.Indexes.CreateOneAsync(Builders<BsonDocument>.IndexKeys.Ascending("_expireAt"),
                        new CreateIndexOptions() { ExpireAfter = TimeSpan.FromSeconds(0) });

            tsk.Wait();

            _indexChecked = true;
        }
    }
public void AddOrUpdateItem(string key, TValue value, TimeSpan timeout)
    {
        var json = value.ToJson();
        dynamic jObject = JObject.Parse(json);
        jObject._expireAt = DateTime.UtcNow.Add(timeout);
        json = jObject.ToString();

        var replacementDocument = BsonSerializer.Deserialize<BsonDocument>(json);
        var filter = new BsonDocument("_id", key);
        var options = new UpdateOptions {IsUpsert = true};
        var tsk = MongoCollection.ReplaceOneAsync(filter, replacementDocument, options);

        try
        {
            tsk.Wait();
        }
        catch (AggregateException ex)
        {
            // TODO: Log

            throw;
        }
    }

以下内容与获取 Mongo 集合上的 getIndices 的命令一起返回。

> db.Users.getIndices()

[ { “v”:1, “钥匙” : { “_id”:1 }, "名称" : "id", “ns”:“AuditDemo.Users” }, { “v”:1, “钥匙” : { “_expireAt”:1 }, “名称”:“_expireAt_1”, "ns" : "AuditDemo.Users", “expireAfterSeconds”:0 } ] >

在我的 AddOrUpdateItem 方法中,我首先将一个泛型类型序列化为 json,以便能够为 expireAt 添加一个动态元素。然后我使用 BsonSerializer 将这个修改后的 json 反序列化为 BsonDocument。此时,BsonDocument 是否将 datetime json 字符串转换为 Bson 日期类型以使 TTL 索引起作用?

findOne 命令的结果

> db.Users.findOne({"_expireAt":{$exists: true}})

{ “_id”:“0”, “用户指南”:{ “值”:“054f6141-e655-41dd-a9d5-39382d3360ab” }, “用户名”:空, “名” : { “价值”:“约旦” }, “姓” : { “价值”:“ACEVEDO” }, “电子邮件” : { “价值”:“JORDAN.ACEVEDO@fake.com” }, "__typ" : "AuditDemo.ConsoleApplication.Models.Wss.UserInfo, ConsoleTest 应用程序,版本=1.0.0.0,文化=中性,PublicKeyToken=null", “_expireAt”:“2015-05-31T10:23:15.8979321Z” } >

【问题讨论】:

  • 请使用编辑按钮将db.YourCollection.getIndices() 的输出添加到您的问题中。
  • @MarkusWMahlberg:我用调用 getIndices 的结果更新了原始帖子。该索引确实存在。但我怀疑这里可能发生的是将 json 文档反序列化为 bson,BsonSerializer 可能不会将 json 日期字符串转换为 Bson 日期数据类型。如果是这种情况,那么如何存储过期的 json 文档。
  • 嗯,让我们检查一下。请添加db.Users.findOne({"_expireAt":{$exists: true}})的输出
  • @MarkusWMahlberg。已添加。

标签: mongodb mongodb-.net-driver mongodb-csharp-2.0


【解决方案1】:

好的,我想出了如何纠正这个日期问题。我从 JSON.Net 获得的日期时间字符串没有存储 BSON 日期对象。所以我不得不在反序列化的 BsonDocument 属性上调用 BsonDateTime.create() 方法并强制它成为 BSON 日期。当它以正确的数据类型存储时,TTL 索引会按预期工作。

        DateTime expiresDate = new DateTime(DateTime.UtcNow.Ticks, DateTimeKind.Utc).Add(timeout);
        var replacementDocument = BsonSerializer.Deserialize<BsonDocument>(json);
        replacementDocument["_expireAt"] = BsonDateTime.Create(expiresDate);
        var filter = new BsonDocument("_id", key);
        var options = new UpdateOptions {IsUpsert = true};
        var tsk = MongoCollection.ReplaceOneAsync(filter, replacementDocument, options);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    相关资源
    最近更新 更多