【问题标题】:How to retrieve latest record using RowKey or Timestamp in Azure Table storage如何在 Azure 表存储中使用 RowKey 或时间戳检索最新记录
【发布时间】:2017-03-28 09:31:37
【问题描述】:

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

我尝试使用Timestamp like 进行查询

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

【问题讨论】:

    标签: c# azure azure-storage


    【解决方案1】:

    尼奥,

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

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

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

    使用这种方法,在查询您的表时,您将能够获取与最新对应的 1 个条目。

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

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

    【讨论】:

    • 请看下面 Gaurav 的回答,因为代码 sn-p 正确指定了 ToString 格式 d19,它用零填充数字。 RowKey 存储为字符串,所以按字符串排序,即“2”大于“1582”。
    • 这里是描述解决方案的 MS 文档的链接docs.microsoft.com/en-us/azure/cosmos-db/…
    • 感谢 Vivien,正在寻找 Order By 功能,使用行键作为 DateTime.UtcNow.Ticks 会有所帮助
    • 如何取出最近24小时的数据?查询中的更改会起作用吗?
    【解决方案2】:

    Azure 表服务不支持Order By 功能,因此使用当前设置的唯一选项是下载所有实体并在客户端按时间顺序对它们进行倒序排序。当表中的实体数量变大时,这显然不是最优解。

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

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

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

    【讨论】:

    • DateTimeValueForRowKey 是什么?它是表存储中的一个字段吗?
    • 这是存储在RowKey字段中的值。
    • 但仅在声明 var rowKey = (DateTime.MaxValue.Ticks - DateTimeValueForRowKey.Ticks).ToString("d19") 之后。执行我们可以在 RowKey 处获取值。在上面的语句之前我们如何才能得到DateTimeValueForRowKey的值。
    • 我建议提出一个新问题。请在此处包含所有详细信息。
    • @GauravMantri Antoni 要求您使用尚不存在的 DateTimeValueForRowKey,因为尚未创建条目...这是创建实体的代码
    【解决方案3】:

    另一种可能某些情况下效果很好的方法是通过生成范围查询或一组范围查询来“智能暴力破解”表。查询,获取您希望工作的值并一次性触发它们。

    在这种情况下,由于行键的格式为 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)。

    请注意,Azure 仅在您为 PartitionKey 提供精确值(在本例中始终为 "raspberrypi")时才使用真正的范围查询。 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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      • 1970-01-01
      • 2018-12-08
      相关资源
      最近更新 更多