Как получить последнюю запись с помощью RowKey или Timestamp в хранилище таблиц Azure
Сложная часть RowKey
является string
который имеет значение, как 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);
2 ответа
Нео,
Если вам нужна последняя запись в вашем разделе, использование строковой даты и времени для ключа строки не является хорошим подходом, поскольку хранилище таблиц сохраняет сущности в порядке возрастания на основе ключа строки.
Если в текущей точке вы можете изменить значение вашего ключа строки, используйте DateTime.UtcNow.Ticks
:
var invertedTimeKey = DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks
При таком подходе при запросе таблицы вы сможете получить 1 запись, соответствующую самой последней.
Если вы не можете изменить значение ключа строки, вам придется извлечь все записи в разделе, то есть загрузить все их в память, а затем упорядочить их, используя метку времени, чтобы получить последнюю. Если у вас много записей, это определенно не очень хороший подход.
var lastResult = results.OrderByDescending(r => r.Timestamp).FirstOrDefault();
Служба таблиц Azure не поддерживает Order By
функциональность, таким образом, с помощью текущей настройки только для вас, чтобы загрузить все объекты и отсортировать их в обратном порядке на клиентской стороне. Это, очевидно, не является оптимальным решением, когда число объектов в таблице становится большим.
Другой вариант (который потребует от вас изменения дизайна приложения) - преобразовать значение даты / времени в обратные тики:
var rowKey = (DateTime.MaxValue.Ticks - DateTimeValueForRowKey.Ticks).ToString("d19")
Это обеспечит добавление последних записей в верхнюю часть таблицы, а не в нижнюю часть таблицы. Чтобы получить последнюю запись, вам нужно просто взять 1-ю сущность из таблицы.
Другой подход, который может хорошо работать в некоторых ситуациях, - это "умный перебор" таблицы путем создания запроса диапазона или набора запросов диапазона для значений, которые, как вы ожидаете, будут работать, и их одновременное отключение..
В этом случае, поскольку ключ строки находится в формате Mon Nov 14 12:26:42 2016
(и предположим, что OP @neo не может его изменить), и им нужны самые последние результаты, тогда вы можете получить хорошую производительность с помощью префиксного запроса (который по-прежнему является лексикографическим запросом диапазона), который, по словам Azure, является самым быстрым тип неточного запроса:
Вторым лучшим является запрос диапазона, который использует
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();