Azure Таблица Получить Следующая Функциональность? - PullRequest
7 голосов
/ 18 января 2020

Что такое хорошая тактика c для запроса Cosmos DB (Table Storage API), чтобы получить «следующий» элемент в Storage? «Далее» определяется как первый элемент, который не был возвращен последним вызовом. Элемент, который был возвращен последним вызовом, хранится в памяти. Используя. NET Framework, C#. Ожидается, что таблица будет содержать около 2 миллионов записей, поэтому сканирование таблицы не является предпочтительным. :)

Хранение таблицы выглядит следующим образом: Ключ раздела (составной из нескольких значений): «0000/00/01 / 2020-01-11». Например, ключ строки один int значение 1. Строка содержит другие строковые данные.

Поэтому пары ключ-значение (ключ раздела и ключ строки) выглядят следующим образом. Приложение предназначено для чтения, но не обязательно использует шаблон хвоста журнала (https://docs.microsoft.com/en-us/azure/cosmos-db/table-storage-design-guide#log -tail-pattern ).

0000/00/01/2020-01-11,1,aaa,x
0000/00/01/2020-01-11,2,aaa,y
0000/00/01/2020-01-11,3,aaa,z
0000/00/01/2020-01-11,4,bbb,x
0001/00/01/2020-01-11,5,aaa,x
0001/00/01/2020-01-11,6,ddd,x

(обратите внимание, что два нижних объекта будут в другой раздел, так что «aaa, x» существует в двух разделах).

Поэтому я думаю, что запрос для получения только одного элемента - это

TableQuery<MyClass> query = new TableQuery<MyClass>()
                    .Where(TableQuery.GenerateFilterCondition("0000/00/01/2020-01-11", QueryComparisons.Equal, "aaa")).Take(1);

Если этот код верен и возвращает " aaa, x "как убедиться, что последующий запрос получит" aaa, y ", а следующий получит" aaa, z ", а следующий получит" bbb, x ", а следующий получит снова" aaa, x " в том же разделе?

Если не имеет смысла создавать расширенные объекты, и вместо этого напрямую запрашивать REST API и, возможно, сохранить элемент, который последний раз использовался в другой таблице, и внешнее соединение или другое условие фильтрации между две таблицы, я открыт для разработки в этом направлении.

Спасибо!

1 Ответ

5 голосов
/ 21 января 2020

Две возможные идеи в зависимости от ваших других требований:

  • Ручная итерация по строкам, отслеживая ваш последний ключ строки
  • Определите запрос, чтобы получить все строки, соответствующие вашим критериям и используйте TableContinuationToken

Возможно, вам придется адаптировать фильтры в моих примерах к вашим точным требованиям, но идея должна подходить в любом случае.


Вручную итерируйте строки, отслеживая ваш последний ключ строки

string currentPartitionKey = "0000/00/01/2020-01-11";
string currentRowKey = "-1";

var query = new TableQuery()
    .Where(TableQuery.CombineFilters(
        TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, currentPartitionKey),
        TableOperators.And,
        // For the very first query, you may be able to omit this condition
        TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, currentRowKey)))
    .Take(1);

// Execute, do stuff
// Switch to next partitionKey if no results were found


Определите запрос, чтобы получить все строки, соответствующие вашим критериям, и используйте TableContinuationToken

Код может выглядеть примерно так:

string currentPartitionKey = "initialParitionkey";
do
{
    TableContinuationToken continuationToken = null;
    do
    {

        TableQuery query = new TableQuery()
            .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, currentPartitionKey));

        var segment = await table.ExecuteQuerySegmentedAsync(query, continuationToken,
            new TableRequestOptions { TableQueryMaxItemCount = 1 }, cancellationToken);
        continuationToken = segment.ContinuationToken;

        // process results
    }
    while (continuationToken != null)

    currentPartitionKey = getNextPartitionKey(currentPartitionKey);
}
while (currentPartitionKey != null)
...