如何使用Azure表存储中的RowKey或Timestamp检索最新记录

时间:2016-11-14 16:55:38

标签: c# azure azure-storage

棘手的部分RowKeystring,其价值类似于Mon Nov 14 12:26:42 2016

我尝试使用Timestamp之类的查询

var lowerlimit = DateTime.UtcNow; // its should be nearer to table timestamp data.
            TableQuery<TemperatureEntity> query2 = new TableQuery<TemperatureEntity>().Where(TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThanOrEqual,lowerlimit));
            var test = table.ExecuteQuery(query2);

MyEntity.cs

  public class MyEntity : TableEntity
    {
        public MyEntity(string partitionKey, string rowKey)
        {
            this.PartitionKey = partitionKey;
            this.RowKey = rowKey;
        }

        public MyEntity() { }

        public Int64 DevideId { get; set; }

        public string RowKey { get; set; }
    }

//下面的查询提供了完整的数据 的 Program.cs的

// Retrieve the storage account from the connection string.
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
                CloudConfigurationManager.GetSetting("StorageConnectionString"));

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            // Create the CloudTable object that represents the "TemperatureData" table.
            CloudTable table = tableClient.GetTableReference("TemperatureData");

            // retrive data
            TableQuery<TemperatureEntity> query = new TableQuery<TemperatureEntity>();
            var data = table.ExecuteQuery(query);

enter image description here

3 个答案:

答案 0 :(得分:19)

新,

如果您需要在分区中拥有最新条目,则使用行键的字符串日期时间不是一个好方法,因为表存储基于行键按升序存储实体。

如果您在当前点可以更改行键的值,请使用DateTime.UtcNow.Ticks

var invertedTimeKey = DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks

通过这种方法,在查询表格时,您可以输入与最新表格相对应的1个条目。

如果您无法更改行键的值,则必须检索分区中的所有条目,这意味着将所有条目加载到内存中,然后使用时间戳对它们进行排序以检索最后一个条目。如果您有很多条目,这绝对不是一个好方法。

var lastResult = results.OrderByDescending(r => r.Timestamp).FirstOrDefault();

答案 1 :(得分:7)

Azure表服务不支持Order By功能,因此当前设置的唯一选项是下载所有实体并在客户端进行chrnological反向排序。当表中的实体数量变大时,这显然不是最佳解决方案。

其他选项(需要您重新设计应用程序)将以反向刻度转换日期/时间值:

var rowKey = (DateTime.MaxValue.Ticks - DateTimeValueForRowKey.Ticks).ToString("d19")

这将确保将最新条目添加到表格的顶部而不是表格的底部。要获取最新条目,您只需从表中获取第一个实体。

答案 2 :(得分:1)

在某些情况下 可能有效的另一种方法是通过生成范围查询或一组范围“智能强力”表。查询,以获取您希望使用的值,并一次将其清除。

在这种情况下,由于行键的格式为Mon Nov 14 12:26:42 2016(并且假设OP @neo不能更改它),并且他们想要最新的结果,那么您可以得到很好的结果前缀查询(仍然是字典范围查询)which Azure says is the fastest type of non-exact query的性能:

第二个最佳选择是使用PartitionKey并对RowKey值范围进行过滤以返回多个实体的范围查询。 PartitionKey值标识特定分区,而RowKey值标识该分区中实体的子集。例如:$filter=PartitionKey eq 'Sales' and RowKey ge 'S' and RowKey lt 'T'

完成这项工作的一个巧妙技巧是利用Mon Nov 14仅是以下日期的事实:

1977-11-14
1983-11-14
1988-11-14
1994-11-14
2005-11-14
2011-11-14
2016-11-14
2022-11-14
2033-11-14
2039-11-14
2044-11-14
etc

因此,只需对Mon Nov 14进行前缀搜索,就可以安全地返回隐含所需年份(2016年)的记录,还可以返回其他1或2年的记录,这些记录可以安全地排除在内存中而不会显着降低性能(例如2011和2022)。

请注意,如果您为PartitionKey提供了一个确切的值(在这种情况下始终为"raspberrypi"),Azure仅使用实数范围查询。 OP的原始查询没有。

String partitionKeyFilter = TableQuery.GenerateFilterCondition(
    propertyName: "PartitionKey",
    operation   : QueryComparisons.Equal,
    givenValue  : "raspberrypi"
);

DateTime today = DateTime.UtcNow;
String todayPrefix = today.ToString( "ddd MMM dd", CultureInfo.InvariantCulture );

String rowKeyFilter = TableQuery.GenerateFilterCondition(
    propertyName: "RowKey",
    operation   : QueryComparisons.GreaterThan,
    givenValue  : todayPrefix 
);

TableQuery<TemperatureEntity> query = new TableQuery<TemperatureEntity>()
{
    FilterString = TableQuery.CombineFilters( partitionKeyFilter, TableOperators.And, rowKeyFilter );
}

List<TemperatureEntity> queryResults = table
    .ExecuteQuery( query )
    .Where( e => e.RowKey.EndsWith( today.ToString(" yyyy") ) ) // Filter current-year in the client.
    .ToList();