Разбивка на DynamoDB через Boto3, NextToken отсутствует, но LastEvaluatedKey есть? - PullRequest
1 голос
/ 27 мая 2019

В документации по страницам boto3 и dynamicodb указывается, что NextToken должен возвращаться при подкачке страниц, и вы затем включаете этот токен в следующий запрос для StartingToken, чтобы возобновить сеанс подкачки (как это происходит при доступе к информации через RESTful API).

Однако, мое тестирование показывает, что он не возвращает NextToken в результатах, а скорее LastEvaluatedKey. Я думал, что мог бы использовать LastEvaluatedKey в качестве токена, но это не работает?

paginator = client.get_paginator('scan')
page_iterator = paginator.paginate(TableName='test1', PaginationConfig={'PageSize': 1 , 'MaxItems': 5000,  'MaxSize': 1 })

    for page in page_iterator:
        print(page)
        break   

Я ожидаю, что объект страницы, возвращаемый из page_iterator, будет включать ключ NextToken, но это не так?

{'Items': [{'PK': {'S': '99'}, 'SK': {'S': '99'}, 'data': {'S': 'Test Item 99'}}], 'Count': 1, 'ScannedCount': 1, 'LastEvaluatedKey': {'PK': {'S': '99'}, 'SK': {'S': '99'}}, 'ResponseMetadata': {'RequestId': 'DUE559L8KVKVH8H7G0G2JH0LUNVV4KQNSO5AEMVJF66Q9ASUAAJG', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Mon, 27 May 2019 14:22:09 GMT', 'content-type': 'application/x-amz-json-1.0', 'content-length': '153', 'connection': 'keep-alive', 'x-amzn-requestid': 'DUE559L8KVKVH8H7G0G2JH0LUNVV4KQNSO5AEMVJF66Q9ASUAAJG', 'x-amz-crc32': '3759060959'}, 'RetryAttempts': 0}}

Чего мне не хватает?

ОБНОВЛЕНИЕ: Как-то связано с этим? Как использовать нумерацию Boto3

1 Ответ

1 голос
/ 29 мая 2019

Есть несколько способов решить эту проблему, используя сканер boto3.

Первый вариант - вызвать build_full_result примерно так:

result = paginator.paginate(TableName="your_table", PaginationConfig={"MaxItems":10, "PageSize": 10}).build_full_result()

, который возвращает ответ с 10элементы, и «NextToken» заполняется при условии, что есть более 10 элементов.Это, вероятно, самый простой способ, вы можете просто воспринимать MaxItems как размер возвращаемой страницы, и если «NextToken» пуст, вы находитесь в конце сканирования.

Я заметил, что если вы не укажете размер страницы, результаты будут такими же, но потребляемая емкость и ScannedCount будут выше.

Другим способом является кодирование 'StartingToken' с использованием TokenEncoder в botocore.paginate напрямую.

Если первоначальный вызов paginator выглядит следующим образом:

pagination_config = {
    "MaxItems": 5000,
    "PageSize": 10,
}

scan_iterator = scan_paginator.paginate(
    TableName="your_table_name",
    PaginationConfig=pagination_config
)

Постраничные результаты будут такими, как описывает вопрос.Первые 10 результатов будут возвращены на первой странице, и «NextToken» не указан, а «LastEvaluatedKey» -.

Чтобы использовать его, закодируйте возвращенный «LastEvaluatedKey» как «ExclusiveStartKey» и передайте его в качестве «StartingToken» в конфигурации пагинации.

from botocore.paginate import TokenEncoder
encoder = TokenEncoder()
for page in scan_iterator:
    if "LastEvaluatedKey" in page:
            encoded_token = encoder.encode({"ExclusiveStartKey": page["LastEvaluatedKey"]})

Затем:

pagination_config = {
    "MaxItems": 500,
    "PageSize": 10,
    "StartingToken": encoded_token
}

Причина кодирования первичного ключа как «ExclusiveStartKey» заключается в том, что именно этого ожидает фактический API сканирования .По сути, пагинаторы кодируют / декодируют «LastEvaluatedKey» и «ExclusiveStartKey» в значения «NextToken» и «StartingToken».Если вы выполните декодирование base64 для «NextToken», возвращаемого при выполнении build_full_result, вы увидите, что оно также использует «ExclusiveStartKey».

...