Таблица Azure получает новые функциональные возможности?

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

Табличное хранилище выглядит следующим образом: Ключ раздела (составной из нескольких значений): «0000/00/01 / 2020-01-11». Например, ключ строки одиночное целое значение 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 и, возможно, сохранить элемент, который последний раз использовался в другой таблице и во внешнем соединении или другом условии фильтра между двумя таблицами, я открыт для проектирования в вместо этого.

Спасибо!


person Snowy    schedule 18.01.2020    source источник
comment
Обнаружил wintellect.com/wp-content/uploads/2017 / 05 /, помогает, но пока не нашел решения.   -  person Snowy    schedule 19.01.2020
comment
Похоже, вам нужна очередь, а не стол   -  person Hong Ooi    schedule 20.01.2020
comment
@HongOoi, извините, мне не нужна очередь, поскольку строки периодически обновляются, а семантика очереди будет означать, что aaa, x будет отброшен после его использования, когда я хочу, чтобы эта строка в разделе после ее использования. Спасибо.   -  person Snowy    schedule 20.01.2020
comment
Итак, 1,2,3,4,5,6 - это ключи строк вашего примера, но вам нужно найти все значения с заданным значением aaa, которые могут быть строками 1,4,5. Это означает, что вы практически ничего не знаете о ключе строки. Вы только знаете, что он должен быть выше, чем последний, который я нашел. У вас будет немного сканирования, я не понимаю, как вы хотите достичь O (1), как вы описываете в награде. Я правильно это понимаю?   -  person Alex AIT    schedule 21.01.2020
comment
Второй момент: я не совсем понимаю ваш образец FilterCondition. Он имеет синтаксис GenerateFilterCondition (string propertyName, string operation, string givenValue)   -  person Alex AIT    schedule 21.01.2020
comment
@AlexAIT Мне не нужны только элементы со значением aaa, но rowkey 1 (aaa, x), затем rowkey 2 (aaa, y), затем rowkey 3 (aaa, z), затем rowkey 4 (bbb, x), затем rowkey 1 ( ааа, х). Исходный пункт непонятен, редактирование. Что касается условия фильтрации, я просто не знаю, как это работает.   -  person Snowy    schedule 22.01.2020


Ответы (1)


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

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

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


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

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)
person Alex AIT    schedule 21.01.2020
comment
Я борюсь с частью CancellationToken. Но экспериментируем ... - person Snowy; 23.01.2020
comment
Вы можете начать с CancellationToken.None, что сложно для реального использования в производстве, в идеале вам нужен другой источник. - person Alex AIT; 23.01.2020
comment
Просеивая перегрузки, большинству, кажется, нужен OperationContext. Я думаю, что ваш образец является ведущим в этом направлении (перегрузка № 12), не могли бы вы показать, какие изменения кода необходимы для компиляции / запуска? - person Snowy; 24.01.2020
comment
Почему бы вам не использовать тот, у которого только query, continuationToken параметры? docs.microsoft.com/en-us/dotnet/api/ - person Alex AIT; 24.01.2020
comment
Или неасинхронную версию, если вы предпочитаете: docs.microsoft.com/en-us/dotnet/api/ - person Alex AIT; 24.01.2020
comment
В // обрабатываемых результатах я устанавливаю фиктивный DynamicTableEntity на segment.Results [0], и каждый раз, когда он выбирает один и тот же первый результат, он не переходит к следующему результату. - person Snowy; 25.01.2020
comment
Похоже, что в этом сегменте есть 3 объекта, а не одна, как я ожидал. - person Snowy; 25.01.2020
comment
Вы должны использовать одну из перегрузок с TableRequestOptions, как в моем ответе. Извините за вводящий в заблуждение комментарий выше. Вы можете передать null вместо OperationContext. Если вы правильно сохраните continueToken, вы не должны получать один и тот же результат несколько раз. - person Alex AIT; 25.01.2020
comment
TableContinuationToken кажется провалом. Вместо этого я попробую ручной метод. - person Snowy; 26.01.2020