Запрос DynamoDB с несколькими полями в AppSync Resolver

У меня есть таблица сообщений DynamoDB с id, content, createdAt (int), userID полями.

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

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "index" : "userid-createdat-index",
    "query" : {
      "expression": "userID = :userID",
        "expressionValues" : {
          ":userID" : $util.dynamodb.toDynamoDBJson($context.arguments.userID)
        }
    }
}

Моя цель - получить сообщения пользователя в течение последних 5 секунд, используя поле createdAt, которое является временем эпохи в миллисекундах. Я бы не хотел использовать операцию сканирования, так как моя таблица будет большой.

Как я могу это сделать? Какой индекс DynamoDB мне нужен для этого?


person Kerem    schedule 26.12.2020    source источник


Ответы (2)


Предполагая, что поле id уникально, вам нужно создать ключ раздела таблицы на id, а затем глобальный вторичный индекс на (userID, createdAt). Запрос на доступ к результату, который вы ищете, должен выглядеть примерно так --key-condition-expression "userID = :userID and createdAt >= :createdAt"

Создание таблицы

aws dynamodb create-table \
--table-name messages \
--attribute-definitions \
AttributeName=id,AttributeType=S \
AttributeName=userID,AttributeType=S \
AttributeName=createdAt,AttributeType=N \
--key-schema AttributeName=id,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 \
--global-secondary-indexes \
"[{\"IndexName\": \"UserIDIndex\",
\"KeySchema\": [{\"AttributeName\":\"userID\",\"KeyType\":\"HASH\"},
{\"AttributeName\":\"createdAt\",\"KeyType\":\"RANGE\"}],
\"Projection\":{\"ProjectionType\":\"ALL\"},
\"ProvisionedThroughput\":     {\"ReadCapacityUnits\":10,\"WriteCapacityUnits\":10}}]"

Пример запроса с GSI

aws dynamodb query \
--table-name messages \
--index-name UserIDIndex \
--key-condition-expression "userID = :userID and createdAt >= :createdAt" \
--expression-attribute-values '{":userID":{"S":"u1"} , ":createdAt":{"N":"2"} }'

Дополнительную информацию о GSI можно найти здесь

если вы используете DynamoDB локально, вы можете добавить --endpoint-url http://localhost:8000 в оба приведенных выше фрагмента кода.

person CruncherBigData    schedule 28.12.2020

Используя предложения из ответа CruncherBigData, я успешно выполнил такой запрос.

Я создал индекс с ключом раздела для userID и ключом сортировки с createdAt. Моя ошибка заключалась в том, что я забыл выбрать Number в качестве типа данных для createdAt во время создания индекса. Сохранение его как String не удалось моему запросу.

Затем я использовал преобразователь запросов для проверки сообщений пользователя за последние 5 секунд:

#set( $messageTimeLimit = 5000 )
#set( $lastNSeconds = $util.time.nowEpochMilliSeconds() - $messageTimeLimit )
{
    "version" : "2018-05-29",
    "operation" : "Query",
    "index" : "userID-createdAt-index",
    "query" : {
      "expression": "userID = :userID and createdAt >= :lastFiveSeconds",
        "expressionValues" : {
          ":lastFiveSeconds" : $util.dynamodb.toDynamoDBJson($lastFiveSeconds),
          ":userID" : $util.dynamodb.toDynamoDBJson($context.arguments.userID)
        }
    }
}
person Kerem    schedule 30.12.2020