Home > Back-end >  How to create MongoDB collection with TTL?
How to create MongoDB collection with TTL?

Time:01-03

I create a collection of objects

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

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

And create the index and some docs

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", "[email protected]");
            collection.InsertOne(user.ToBsonDocument());
            var user1 = new User("Petya", "[email protected]");
            collection.InsertOne(user1.ToBsonDocument());
            var user2 = new User("Kolya", "[email protected]");
            collection.InsertOne(user2.ToBsonDocument());
            count = collection.CountDocuments(new BsonDocument());

But when I see http://localhost:8081/db/dbtest/ then I do not see any TTL and documents do not expire after 30 secs.

What I do wrong? How to create collection or documents in it with TTL?

CodePudding user response:

Your user object doesn't have the field you specified on the index

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; }
}

Also, the default convention for serialization in MongoDB C# Driver is not camel case so you'll need to update your index to the following:

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

You might also want to embrace the type safety that C# and the MongoDB Driver gives you by using your User type instead of the BsonDocument. Below is an example of how to do this.

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", "[email protected]", DateTime.UtcNow);
collection.InsertOne(user);
var user1 = new User("Petya", "[email protected]", DateTime.UtcNow);
collection.InsertOne(user1);
var user2 = new User("Kolya", "[email protected]", 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; }
}

You might notice that the documents don't get deleted at once but as said in the MongoDB docs

The background task that removes expired documents runs every 60 seconds. As a result, documents may remain in a collection during the period between the expiration of the document and the running of the background task. https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation

  • Related