【问题标题】:How to create MongoDB collection with TTL?如何使用 TTL 创建 MongoDB 集合?
【发布时间】:2022-01-02 10:28:01
【问题描述】:

我创建了一个对象集合

public class User
{
public User(string fullname, string email)
{
Fullname = fullname;
Email = email;
}

    public string Fullname { get; }
    public string Email { get; }
}

并创建索引和一些文档

var collection = _database.GetCollection(“bar”);
collection.Indexes.CreateOne(new CreateIndexModel
(new BsonDocument(“lastModifiedDate”, 1), new CreateIndexOptions { ExpireAfter = new TimeSpan(0, 0, 30) }));

            var user = new User("Vasya", "billgates@ms.com");
            collection.InsertOne(user.ToBsonDocument());
            var user1 = new User("Petya", "Petya@ms.com");
            collection.InsertOne(user1.ToBsonDocument());
            var user2 = new User("Kolya", "Kolya@ms.com");
            collection.InsertOne(user2.ToBsonDocument());
            count = collection.CountDocuments(new BsonDocument());

但是当我看到 http://localhost:8081/db/dbtest/ 然后我看不到任何 TTL 并且文档在 30 秒后不会过期。

我做错了什么?如何使用 TTL 在其中创建集合或文档?

【问题讨论】:

  • TTL 工作器仅每 60 秒运行一次,因此删除这些文档最多可能需要 90 秒。
  • 好的,我又测试了,等了2分钟;没有效果,集合还活着...可能我需要在其上创建索引过期的字段 lastModifiedDate 吗?
  • 如果 lastModifiedDate 不包含日期类型,文档将永远不会被删除。

标签: c# mongodb mongodb-.net-driver


【解决方案1】:

您的用户对象没有您在索引中指定的字段

public class User
{
    public User(string fullname, string email, DateTime lastModifiedDate) 
    {
        Fullname = fullname;
        Email = email;
        LastModifiedDate = lastModifiedDate;
    }

    public string Fullname { get; }
    public string Email { get; }
    public DateTime LastModifiedDate { get; }
}

此外,MongoDB C# 驱动程序中序列化的默认约定不是驼峰式大小写,因此您需要将索引更新为以下内容:

var collection = _database.GetCollection("bar");
collection.Indexes.CreateOne(new CreateIndexModel
(new BsonDocument("LastModifiedDate", 1), new CreateIndexOptions { ExpireAfter = new TimeSpan(0, 0, 30) }));

您可能还希望通过使用用户类型而不是 BsonDocument 来接受 C# 和 MongoDB 驱动程序为您提供的类型安全性。以下是如何执行此操作的示例。

using MongoDB.Driver;

var client = new MongoClient();
var database = client.GetDatabase("test");
var collection = database.GetCollection<User>("users");
await collection.Indexes.CreateOneAsync(
    Builders<User>.IndexKeys.Ascending(x => x.LastModifiedDate),
    new CreateIndexOptions { ExpireAfter = new TimeSpan(0, 0, 30) });

var user = new User("Vasya", "billgates@ms.com", DateTime.UtcNow);
collection.InsertOne(user);
var user1 = new User("Petya", "Petya@ms.com", DateTime.UtcNow);
collection.InsertOne(user1);
var user2 = new User("Kolya", "Kolya@ms.com", DateTime.UtcNow);
collection.InsertOne(user2);

for (var i = 0; i < 10; i++)
{
    var count = await collection.CountDocumentsAsync(Builders<User>.Filter.Empty);
    Console.WriteLine($"Count: {count} @ {DateTime.UtcNow}");
    await Task.Delay(10000);
}


// Count: 4 @ 02/01/2022 11:42:13
// Count: 4 @ 02/01/2022 11:42:23
// Count: 4 @ 02/01/2022 11:42:33
// Count: 4 @ 02/01/2022 11:42:43
// Count: 4 @ 02/01/2022 11:42:53
// Count: 1 @ 02/01/2022 11:43:03
// Count: 1 @ 02/01/2022 11:43:13
// Count: 1 @ 02/01/2022 11:43:23
// Count: 1 @ 02/01/2022 11:43:33
// Count: 0 @ 02/01/2022 11:43:43


public class User
{
    public User(string fullname, string email, DateTime lastModifiedDate)
    {
        Fullname = fullname;
        Email = email;
        LastModifiedDate = lastModifiedDate;
    }

    public string Fullname { get; }
    public string Email { get; }
    public DateTime LastModifiedDate { get; }
}

您可能会注意到文档不会立即被删除,而是如 MongoDB 文档中所述

删除过期文档的后台任务每 60 秒运行一次。因此,在文档到期和后台任务运行之间的时间段内,文档可能会保留在集合中。 https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation

【讨论】:

  • 顺便说一句:当我使用这种方式创建文档 时,我的数据库包含具有字段 Fullname、Email 的集合,但没有字段 LastModifiedDate 。可能这就是为什么带有TTL的索引不起作用的原因?
  • 如果我以这种方式创建它可以工作,即该字段存在并且建立了 TTL 的索引并删除了记录: var document = new BsonDocument { { "name", "MongoDB" }, { "type" , "数据库" }, { "count", 1 }, { "LastModifiedDate", DateTime.UtcNow}, { "info", new BsonDocument { { { "x", 203 }, { "y", 102 } }} } ; collection.InsertOne(document);
  • 但是如果我使用 c# 类创建文档,则集合中没有 LastModifiedDate 字段
  • @ZedZip 如果你的类上有一个带有 LastModifiedDate 的属性,那么它将被序列化为 BSON 文档并存储。
  • 我找到了原因,这对我来说很奇怪,但它是:public DateTime LastModifiedDate { get; set;} - 我添加了“set;”它也有效,索引也有效。谢谢!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 2016-05-14
  • 2020-12-07
  • 1970-01-01
相关资源
最近更新 更多