AWS DynamoDB при обратном сканировании игнорирует LastEvaluatedKey - PullRequest
3 голосов
/ 24 октября 2019

Я использую AWS для хостинга API с API Gateway и прямой интеграцией DynamoDB.

Сейчас я пытаюсь добавить функцию разбивки на страницы для моего приложения, и мне трудно реализовать ее на 100%. Проблема, с которой я сталкиваюсь, - это когда я сканирую в обратном направлении, и я дам вам пример, чтобы лучше понять проблему.

Представьте, что у меня есть список из 20 элементов и размер страницы 5.

  1. Когда я запрашиваю свою таблицу, первый запрос вернет 1, 2, 3, 4, 5. Ожидаемое поведение!
  2. Когда я запрашиваю мою таблицу, передавая ей lastEvaluatedKey из пятого элемента, она возвращает 6, 7, 8, 9, 10. Ожидаемое поведение.
  3. Теперь моя проблема остается, когда я запрашиваю, используя флаг ScanIndexForward=false. Это значит, что я не хочу двигаться вперед. Вместо этого я хочу предыдущие элементы из lastEvaluatedKey. Дело в том, что если я использую lastEvaluatedKey, полученный из моего последнего запроса, вместо того, чтобы иметь что-то вроде 5, 4, 3, 2, 1, у меня будет 4, 3, 2, 1.

Элемент из lastEvaluatedKey или вызовэто head, если хотите, пропускается.

Если вы представляете нормальное поведение внутри таблицы, когда вы нажимаете next page и previous page, это будет означать, что когда вы перейдете на вторую страницу и вернетесь на первую страницу, выДля предложенного сценария я получу только 4 элемента вместо одного.

Наконец, я попробовал тот же запрос с AWS CLI, и результат тот же. Поговорив с ребятами из службы поддержки, они подтвердили, что это ожидаемое поведение.

Я просто хочу узнать, как люди относятся к этому сценарию, так как я знаю, что Amazon использует его в работе, поэтому должно бытьспособ сделать это.

1 Ответ

2 голосов
/ 24 октября 2019

Чтобы понять поведение, которое вы видели, вы должны понимать, что первоначальная цель LastEvaluatedKey состояла не в том, чтобы сделать произвольный доступ к какому-либо месту в середине запроса так, как вы хотели его использовать, а скорее к возобновлению. запрос после того, как он остановился на границе страницы. Имея это в виду, когда ScanIndexForward=false предполагает, что продолжает текущий обратный запрос;Поэтому, если вы передадите LastEvaluatedKey=5, предполагается, что ранее возвращенная последовательность была 10, 9, 8, 7, 6, 5 (последний возвращенный элемент был 5) - так что теперь будет переходить к 4, 3, 2, 1. Точно так же, как выПримечание.

Если для ваших целей вам также необходим элемент «5», вы можете просто прочитать этот элемент отдельно в отдельном запросе. Это не будет стоить вам дороже, потому что Amazon выставляет вам счет по размеру прочитанного - это не дешевле, когда несколько предметов возвращаются в одном запросе. Также задержка не увеличится, если вы будете выполнять чтение и запрос параллельно.

Обновление:

Как заметил Чарльз в комментарии ниже, для коротких элементов и коротких страниц - дополнительный запрос GetItem«5» на самом деле будет стоить вам другого RCU, что может быть значительным, так что это не очень хорошая идея.

Так что есть еще один вариант, который вообще не использует LastEvaluatedKey. Вместо этого Query позволяет указать в KeyConditionExpression не только нужный ключ раздела, но и диапазон ключей сортировки. Вы можете указать диапазон "sort <= 5", и это приведет к получению последней (когда ScanIndexForward = false) страницы элементов для сортировки <= 5 - включая 5. Я думаю, что это действительно даже лучшее решение, чем то, что я предложилвыше, потому что это не тратит впустую дополнительный RCU. </p>

...