Введение
Команде упаковки нужны заказы NEW разных клиентов. Первичный ключ клиента и даты не может обслужить этот шаблон доступа одним Query основной таблицы. Вы добавите глобальный вторичный индекс, выберете проекцию, запросите фактическую очередь и увидите переход упакованного заказа между разделами индекса после записи в основную таблицу.
Сначала выполните работу «Запросите заказы по ключам раздела и сортировки». Эта новая VM подготавливает только основную таблицу, синтетические записи, эталонную таблицу и оболочку приложения. Создание индекса и настройка поиска — ваша работа. Используйте /home/labex/project, официальный AWS CLI и AWS View.
Связь с сертификацией
| Сертификация | Задача экзамена | Практика |
|---|---|---|
| Solutions Architect – Associate (SAA-C03) | Задача 3.3 | Вторичные индексы DynamoDB и проекция атрибутов. |
| Developer – Associate (DVA-C02) | Задача 1.3 | Вторичные индексы DynamoDB и проекция атрибутов. |
| Data Engineer – Associate (DEA-C01) | Задача 2.4 | Базовая практика: Вторичные индексы DynamoDB и проекция атрибутов. |
Обзор работы

Добавьте альтернативный шаблон доступа
На этом шаге вы добавите индекс для очереди упаковки, которой нужны заказы NEW разных клиентов. Подготовленная таблица использует customer_id и order_key; Query основной таблицы не может выбрать всех клиентов по статусу, поскольку status не является её ключом раздела. Глобальный вторичный индекс (GSI) предоставляет другое представление тех же элементов по ключам раздела и сортировки.
Поиск по клиенту и очередь упаковки решают разные бизнес-задачи на одних заказах. GSI позволяет очереди напрямую выбирать раздел по статусу для разных клиентов. Фильтр статуса в Query по клиенту всё равно проверял бы только раздел этого клиента и не создал бы альтернативный путь доступа для очереди.

Таблица заказов и три синтетические записи подготовлены независимо, чтобы вы сосредоточились на новом шаблоне доступа. Сначала изучите их; оставьте все записи без изменений, кроме изучаемого обновления статуса.
cd /home/labex/project
aws dynamodb describe-table --table-name labex-d03-orders --query 'Table.KeySchema'
aws dynamodb scan --table-name labex-d03-orders --consistent-read
Добавьте StatusDateIndex со status как ключом раздела и order_key как ключом сортировки. Проекция определяет атрибуты, хранимые индексом. INCLUDE добавляет amount; ключи таблицы и индекса включаются автоматически. Неключевой атрибут source останется только в основной таблице. Хранение и записи индекса имеют стоимость в AWS.
aws dynamodb update-table \
--table-name labex-d03-orders \
--attribute-definitions AttributeName=status,AttributeType=S AttributeName=order_key,AttributeType=S \
--global-secondary-index-updates '[{"Create":{"IndexName":"StatusDateIndex","KeySchema":[{"AttributeName":"status","KeyType":"HASH"},{"AttributeName":"order_key","KeyType":"RANGE"}],"Projection":{"ProjectionType":"INCLUDE","NonKeyAttributes":["amount"]}}}]'
aws dynamodb describe-table \
--table-name labex-d03-orders \
--query 'Table.GlobalSecondaryIndexes[].{Name:IndexName,State:IndexStatus,Keys:KeySchema,Projection:Projection}'
Продолжайте только когда StatusDateIndex сообщает ACTIVE. Создание может занять время в AWS; повторяйте команду describe, пока индекс создаётся. Команда ожидания table-exists не доказывает готовность нового индекса. AWS View показывает индекс внутри карточки таблицы после сообщения сервиса.
Запросите индекс статуса и изучите его проекцию
На этом шаге вы прочитаете очередь NEW через альтернативные ключи. --index-name выбирает GSI. Условие ключа использует равенство status; фильтр сканирования основной таблицы сначала прочитал бы посторонние элементы.
aws dynamodb query \
--table-name labex-d03-orders \
--index-name StatusDateIndex \
--key-condition-expression '#state = :state' \
--expression-attribute-names '{"#state":"status"}' \
--expression-attribute-values '{":state":{"S":"NEW"}}'
Индекс возвращает O100 Ada и O200 Bob, каждый с amount. Атрибут source отсутствует, поскольку не был проецирован. Получение дополнительных атрибутов основной таблицы потребовало бы отдельного чтения по ключу.
Обновления GSI асинхронны в AWS, а чтения GSI имеют итоговую согласованность. Не добавляйте --consistent-read к Query GSI: такой запрос отклоняется с ValidationException. Подождите и повторите чтение, если недавняя запись ещё не достигла индекса; не считайте устаревший результат доказательством отказа записи.
Предоставленное приложение order-lookup из предыдущей работы читает обычные настройки lookup.json. Запишите запрос для выбора этого индекса и очереди NEW. Heredoc с кавычками записывает JSON буквально; ConsistentRead: false явно задаёт выбор чтения индекса.
cat > lookup.json <<'JSON'
{
"paginate": true,
"request": {
"TableName": "labex-d03-orders",
"IndexName": "StatusDateIndex",
"KeyConditionExpression": "#state = :state",
"ExpressionAttributeNames": {
"#state": "status"
},
"ExpressionAttributeValues": {
":state": {
"S": "NEW"
}
},
"ConsistentRead": false
}
}
JSON
./order-lookup
Приложение возвращает те же два заказа. Раскройте StatusDateIndex в AWS View и сравните фактическую проекцию с результатом поиска. Сохранение обоих клиентов правильно для очереди статуса, хотя представление конкретного клиента потребовало бы другого шаблона ключей.
Наблюдайте переход заказа между очередями статусов
На этом шаге вы упакуете O100 и увидите перемещение его записи индекса. GSI следует записям основной таблицы; напрямую в индекс вы не записываете. Обновление status меняет раздел индекса элемента, а его основной первичный ключ остаётся тем же.
aws dynamodb update-item \
--table-name labex-d03-orders \
--key '{"customer_id":{"S":"ada"},"order_key":{"S":"2026-10-01#O100"}}' \
--update-expression 'SET #state = :state' \
--expression-attribute-names '{"#state":"status"}' \
--expression-attribute-values '{":state":{"S":"PACKED"}}' \
--return-values ALL_NEW
./order-lookup
Теперь очередь NEW содержит только O200 Bob. Запросите PACKED, чтобы подтвердить появление O100 рядом с O101, а не его исчезновение из сервиса.
aws dynamodb query \
--table-name labex-d03-orders \
--index-name StatusDateIndex \
--key-condition-expression '#state = :state' \
--expression-attribute-names '{"#state":"status"}' \
--expression-attribute-values '{":state":{"S":"PACKED"}}'
Ожидайте O100 и O101 Ada в PACKED. В AWS повторяйте эти чтения до видимого распространения изменения в индекс. Ответ обновления и согласованное чтение основной таблицы — авторитетное немедленное состояние элемента; GSI — производное представление с итоговой согласованностью. AWS View показывает новый статус O100 и поиск NEW, содержащий только O200.

Удалите собственный индекс и таблицу
На этом шаге вы удалите альтернативное представление, затем собственную таблицу. Удаление индекса оставляет элементы основной таблицы целыми; удаление таблицы удаляет элементы и оставшиеся индексы. Называйте только собственные ресурсы.
aws dynamodb update-table \
--table-name labex-d03-orders \
--global-secondary-index-updates '[{"Delete":{"IndexName":"StatusDateIndex"}}]'
aws dynamodb describe-table \
--table-name labex-d03-orders \
--query 'Table.GlobalSecondaryIndexes'
Продолжайте, когда список индексов пуст. В AWS повторяйте DescribeTable во время удаления. В этот момент таблица всё ещё содержит три элемента.
aws dynamodb scan --table-name labex-d03-orders --consistent-read --select COUNT
aws dynamodb delete-table --table-name labex-d03-orders
aws dynamodb wait table-not-exists --table-name labex-d03-orders
aws dynamodb list-tables
aws dynamodb get-item \
--table-name labex-d03-reference \
--key '{"id":{"S":"platform"}}' \
--consistent-read
Таблица заказов и её индекс отсутствуют; эталонная заметка остаётся keep unchanged. Успешная инвентаризация и чтение эталонного ресурса отличают очистку от отключённого сервиса. AWS View сохраняет только посторонний эталонный ресурс. Временное подключение заканчивается с VM.
Резюме
Вы добавили GSI для очереди статуса разных клиентов, выбрали проецируемые атрибуты и использовали ключи индекса в фактических запросах. Обновление статуса основной таблицы переместило заказ между разделами индекса, не меняя первичный ключ. Вы различили немедленное состояние основной таблицы и итоговое распространение в индекс, затем удалили только собственные индекс и таблицу.
Подробнее см. в документации AWS: Глобальные вторичные индексы, проекции и согласованность.



