Search DynamoDB in C # for time series data in a range using GSI
It is a method to search the time series data stored in Amazon DynamoDB in C # by specifying the range using GSI (Global Secondary Index).
[Preparation 1] Data
So that you can save the data of the following structure
[DynamoDBTable("SampleTable")]
public class Sample
{
/// <summary>"Sample Table" table hash key</summary>
[DynamoDBHashKey]
public string Id { get; set; }
/// <summary>Range key for the "Sample Table" table</summary>
[DynamoDBRangeKey]
public string DateAndTime { get; set; }
/// <summary>「Date-Time-index "GSI hash key</summary>
[DynamoDBGlobalSecondaryIndexHashKey]
public string Date { get; set; }
/// <summary>「Date-Time-index ”GSI range key</summary>
[DynamoDBGlobalSecondaryIndexRangeKey]
public string Time { get; set; }
[DynamoDBProperty]
public string Message { get; set; }
public override string ToString()
{
return $"{Id} / {DateAndTime} / {Message}";
}
}
From the AWS Console, prepare a SampleTable
table with ʻId and
DateAndTime` as keys.
Next, create 10 data using the SaveAsync
method as shown below.
//Prepare an object to access DynamoDB
using var client = new AmazonDynamoDBClient(RegionEndpoint.APNortheast1);
using var context = new DynamoDBContext(client);
//Create 10 data
for (var i = 0; i < 10; i++)
{
var now = DateTime.Now;
await context.SaveAsync(new Sample
{
Id = $"{i % 3 + 1:D3}",
DateAndTime = $"{now:yyyy-MM-dd HH:mm:ss.fff}",
Date = $"{now:yyyy-MM-dd}",
Time = $"{now:HH:mm:ss}",
Message = $"message- {i + 1}"
});
//I want to shift the save time, so wait 500 msec
await Task.Delay(500);
}
Get all the data using the ScanAsync
method as shown below.
//Get all data
var listAll = await context.ScanAsync<Sample>(null).GetRemainingAsync();
Console.WriteLine("--- listAll");
listAll.OrderBy(n => n.DateAndTime).ToList().ForEach(Console.WriteLine);
Then, you can get the data as below.
--- listAll
001 / 2020-08-11 11:40:40.236 /message- 1
002 / 2020-08-11 11:40:41.224 /message- 2
003 / 2020-08-11 11:40:41.756 /message- 3
001 / 2020-08-11 11:40:42.293 /message- 4
002 / 2020-08-11 11:40:42.824 /message- 5
003 / 2020-08-11 11:40:43.355 /message- 6
001 / 2020-08-11 11:40:43.877 /message- 7
002 / 2020-08-11 11:40:44.412 /message- 8
003 / 2020-08-11 11:40:44.936 /message- 9
001 / 2020-08-11 11:40:45.458 /message- 10
[Preparation 2] GSI
From the AWS Console, you can confirm that the data is saved as shown below.
At the end of the preparation, prepare a Date-Time-index
index (GSI) with Date
and Time
as keys from the AWS Console so that you can search by specifying the date and time.
Now you are ready to go.
[Scenario 1] I want to get the data of Id = 001
Get the data using the QueryAsync ()
method with 001
as the hash key as shown below.
var list01 = await context.QueryAsync<Sample>("001").GetRemainingAsync();
Console.WriteLine("--- list01");
list01.OrderBy(n => n.DateAndTime).ToList().ForEach(Console.WriteLine);
Then, you can get the data as below.
--- list01
001 / 2020-08-11 11:40:40.236 /message- 1
001 / 2020-08-11 11:40:42.293 /message- 4
001 / 2020-08-11 11:40:43.877 /message- 7
001 / 2020-08-11 11:40:45.458 /message- 10
Only the data with Id of 001 can be obtained.
[Scenario 2] I want to acquire data from 11:40:42 to 11:40:43 on 2020-08-11.
Specify the GSI name Date-Time-index
as shown below, specify 2020-08-11
for the hash key, and QueryOperator.Between
and 11:40:42-for the range key. Get the data using the
QueryAsync () method with 11:40:43
.
var list02 = await context.QueryAsync<Sample>(
"2020-08-11",
QueryOperator.Between,
new List<object>
{
"11:40:42",
"11:40:43"
},
new DynamoDBOperationConfig
{
IndexName = "Date-Time-index" //Specify the GSI to use
}).GetRemainingAsync();
Console.WriteLine("--- list02");
list02.OrderBy(n => n.DateAndTime).ToList().ForEach(Console.WriteLine);
Then, you can get the data as below.
--- list02
001 / 2020-08-11 11:40:42.293 /message- 4
002 / 2020-08-11 11:40:42.824 /message- 5
003 / 2020-08-11 11:40:43.355 /message- 6
001 / 2020-08-11 11:40:43.877 /message- 7
Only the data of 11: 40: 42 --11: 40: 43
can be obtained across the hash key ʻId of the
SampleTable` table.
at the end
I was able to search by specifying the date and time using GSI.
However, when it comes to cost considerations and NoSQL-like design,
Please let me know if there is a better way m (_ _) m