В документации по пагинаторам boto3 и dynamodb указано, что 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
Потому что я возвращаю эту страницу данных клиенту HTTP API. Мне также нужно будет вернуть этот токен, чтобы они могли вернуться и получить следующую страницу по следующему запросу.





Есть несколько способов решить эту проблему с помощью пагинатора сканирования 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.
Если первоначальный вызов пагинатора выглядит так:
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».
Спасибо. В итоге я просто не использовал API разбиения на страницы, а просто взял кодировку LastEvaluatedKey base64, а затем позволил передать ее обратно при последующем вызове. Итак, хотя я на самом деле не разбиваю его по страницам, я думаю, что это позволит более эффективно использовать его, а количество чтений впустую будет меньше.
зачем вам токен, если вы все равно получаете page_iterator для перебора страниц?