Sometimes you need to keep data for a certain period of time and then delete it. If you want to do it yourself, you are doing something time-consuming and unreasonable. But you can do this using the Expiration time for the MongoDB database or the TTL for Radis. In this article, we want to create an index in the Mongo database to specify how long the entered data will be deleted automatically.
To do this, we first create an Asp.Net Core WebApplication project. Then we need to create a Repository to read and write data in Mongo. To work with the MongoDB database, you must install the MongoDB.Driver package.
User related repository:

public class UserMongoDbRepository : IUserRepository
{
    private readonly IMongoCollection<User> _userCollection;
    private readonly ILogger<UserMongoDbRepository> _logger;

    public UserMongoDbRepository(ILogger<UserMongoDbRepository> logger, IOptions<MongoDbConfiguration> options)
    {
        _logger = logger; 
        var mongoClient = new MongoClient(options.Value.ConnectionString);
        var database = mongoClient.GetDatabase(options.Value.DatabaseName);
        _userCollection = database.GetCollection<User>(options.Value.CollectionName);
    }
 
    public async Task AddUser(User user, CancellationToken cancellationToken)
    {
        await _userCollection.InsertOneAsync(user, null, cancellationToken);
    }
    public async Task<User> GetUserById(int id, CancellationToken cancellationToken)
    {
        var filter = Builders<User>.Filter.Eq(a => a.Id, id);

        var result = await _userCollection.FindAsync(filter, cancellationToken: cancellationToken);

        return await result.FirstOrDefaultAsync(cancellationToken);
    }
}

The implemented repository includes two methods of adding and reading. But if we want the data to be deleted automatically after a certain period of time, we have to add the index settings to MongoDB. To do this, we create a one called CreateExpireIndex that creates the index-related settings.

private void CreateExpireIndex(MongoDbConfiguration mongoDbConfiguration)
{
    var isValidExpireFormat = TimeSpan.TryParseExact(mongoDbConfiguration.ExpireAfter,
        mongoDbConfiguration.ExpireFormat,
        CultureInfo.InvariantCulture,
        out TimeSpan expireAfter);

    if (isValidExpireFormat)
    {
        const string _expireAt = "ExpireAt";
        var expireIndex = new IndexKeysDefinitionBuilder<User>().Ascending(c => c.CreationTime);

        var index = _userCollection.Indexes.List().ToList()
            .Where(a => a["name"] == _expireAt)
            .Select(a => new
            {
                ExpireAfterSeconds = a.GetElement("expireAfterSeconds").Value.ToString()
            }).FirstOrDefault();

        if (index != null)
        {
            var registeredExpireAfter = TimeSpan.FromSeconds(Convert.ToInt64(index.ExpireAfterSeconds));
            if (registeredExpireAfter == expireAfter)
            {
                return;
            }
            _userCollection.Indexes.DropOne(_expireAt);
            _logger.LogInformation($"Index deleted. {registeredExpireAfter.ToString(mongoDbConfiguration.ExpireFormat)}");
        }

        _userCollection.Indexes.CreateOne(new CreateIndexModel<User>(expireIndex, new CreateIndexOptions
        {
            Name = _expireAt,
            ExpireAfter = expireAfter
        }));
        _logger.LogInformation($"Index created. {expireAfter.ToString(mongoDbConfiguration.ExpireFormat)}");
    }
}

We read the specified time for clearing from appsettings.json and create a TimeSpan from it. Then, if the data entered in appsettings.json is valid, the indexing operation will continue. If the desired index is already added and you add the index again, you will encounter an error, so we first receive the list of created indexes, and if the index does not exist or the index exists, but its value with the value If reading from appsettigs.json is not equal, the previous index will be deleted and a new index will be added, but no action will be taken if the index value is equal to the value read from appsettings.json. Then we have to call this method in the repository constructor.

public UserMongoDbRepository(ILogger<UserMongoDbRepository> logger, IOptions<MongoDbConfiguration> options)
{
    _logger = logger; 
    var mongoClient = new MongoClient(options.Value.ConnectionString);
    var database = mongoClient.GetDatabase(options.Value.DatabaseName);
    _userCollection = database.GetCollection<User>(options.Value.CollectionName);
    CreateExpireIndex(options.Value);
}

Finally, we need to register the repository created in the services:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MongoDbConfiguration>(a => Configuration.GetSection(nameof(MongoDbConfiguration)).Bind(a));
    services.AddControllers();
    services.AddSingleton<IUserRepository, UserMongoDbRepository>();
}

MongoDbConfiguration model:

public class MongoDbConfiguration
{
    public string DatabaseName { get; set; }
    public string ConnectionString { get; set; }
    public string CollectionName { get; set; }
    public string ExpireAfter { get; set; }
    public string ExpireFormat { get; set; }
}

Value of appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "MongoDbConfiguration": {
    "ConnectionString": "connectionString",
    "DatabaseName": "TestDb",
    "CollectionName": "User",
    "ExpireFormat": "dd':'hh':'mm':'ss",
    "ExpireAfter": "02:00:00:00"
  }
}

Posted in appsettings.json, the registration time is 2 days. Note that if the entered format is not correct, the index you want will not be created. You must first make sure that the format (ExpireFormat) and its value (ExpireAfter) are correct, and then run the program.

;)

Powered by Froala Editor

Comments