DynamoDB запрашивает вторичный индекс, как определить индексы
Я ходил вокруг и вокруг, и просто не ясно, что делать.
У меня есть простая таблица, где я хочу сделать запросы к нескольким столбцам. Насколько я понимаю, это означает создание вторичного индекса для каждого столбца, к которому необходимо выполнить запрос. Я определил таблицу - используя Serverless Framework serverless.yml
- и я получаю множество странных сообщений об ошибках.
Электрический ток serverless.yml
определение это:
resources:
Resources:
MessagesDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: messageId
AttributeType: S
- AttributeName: room
AttributeType: S
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: messageId
KeyType: HASH
- AttributeName: userId
KeyType: RANGE
LocalSecondaryIndexes:
- IndexName: roomIndex
KeySchema:
- AttributeName: room
KeyType: HASH
Projection:
ProjectionType: "KEYS_ONLY"
- IndexName: userId
KeySchema:
- AttributeName: userId
KeyType: HASH
Projection:
ProjectionType: "KEYS_ONLY"
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:custom.tableName}
Это должно быть что-то вроде сервиса Slack - и поэтому я хочу запросить записи из комнаты, пользователем и так далее.
Это определение имеет смысл, исходя из документации, которую я смог найти. Предполагается объявить атрибуты для столбцов, используемых в индексах, и я сделал это. KeySchema - мне действительно нужно только поле messageId, но в сообщении об ошибке указано, что ему нужен индекс RANGE, поэтому я добавил поле userId в KeySchema просто для того, чтобы закрыть это. Вторичные индексные поля выглядят правильно, основываясь на документации, которую я смог найти.
С этим определением я получаю эту ошибку при попытке развертывания с использованием serverless deploy
An error occurred: MessagesDynamoDBTable - Property AttributeDefinitions is inconsistent
with the KeySchema of the table and the secondary indexes.
Я перепробовал несколько вариантов и получил и другие странные ошибки. Ниже приведены некоторые из них, но я не помню, какие были соответствующие изменения в определении.
An error occurred: MessagesDynamoDBTable - One or more parameter values were invalid:
Index KeySchema does not have a range key for index: userId (Service: AmazonDynamoDBv2; Status Code: 400;
Error Code: ValidationException; Request ID: 1KFA2IMASC12HRLLDPG753CU63VV4KQNSO5AEMVJF66Q9ASUAAJG).
An error occurred: MessagesDynamoDBTable - 1 validation error detected: Value '[com.amazonaws.dynamodb.v20120810.KeySchemaElement@aa4cdc91,
com.amazonaws.dynamodb.v20120810.KeySchemaElement@d2cd6f64, com.amazonaws.dynamodb.v20120810.KeySchemaElement@4d7c1f9,
com.amazonaws.dynamodb.v20120810.KeySchemaElement@d2cd6f64]' at 'keySchema' failed to satisfy constraint: Member must have length less
than or equal to 2 (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: BOVVBQ1F35VA18CCF3L5MSKS1FVV4KQNSO5AEMVJF66Q9ASUAAJG).
An error occurred: MessagesDynamoDBTable - Property AttributeDefinitions is inconsistent with the KeySchema
of the table and the secondary indexes.
An error occurred: MessagesDynamoDBTable - One or more parameter values were invalid: Index KeySchema does not have a range key for index:
userIdIndex (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: KFS63VSPKDUC60DV6U2V47UP27VV4KQNSO5AEMVJF66Q9ASUAAJG).
An error occurred: MessagesDynamoDBTable - One or more parameter values were invalid: Table KeySchema does not have a range key,
which is required when specifying a LocalSecondaryIndex (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 86Q2JSPM6Q9UPNIEOVHALLIIQJVV4KQNSO5AEMVJF66Q9ASUAAJG).
1 ответ
Причина, по которой он не работает, заключается в том, что ключи в локальном вторичном индексе должны иметь тот же ключ раздела, что и таблица. Так что в вашем случае ваши локальные вторичные индексы должны иметь messageId
как его HASH
ключ и room
а также userId
как RANGE
ключи на их соответствующие индексы. И так как ваша таблица уже набрана (messageId, userId)
тогда вам не нужно userId
Локальный вторичный индекс.
Эта установка будет технически работать:
MessagesDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: messageId
AttributeType: S
- AttributeName: room
AttributeType: S
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: messageId
KeyType: HASH
- AttributeName: userId
KeyType: RANGE
LocalSecondaryIndexes:
- IndexName: roomIndex
KeySchema:
- AttributeName: messageId
KeyType: HASH
- AttributeName: room
KeyType: RANGE
Projection:
ProjectionType: KEYS_ONLY
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:custom.tableName}
Однако, если вы хотите сделать запрос по комнатам и пользователям, то вы, вероятно, захотите использовать другой дизайн таблицы. То, что вы пытаетесь сделать, в конечном итоге требует от вас всегда запрашивать таблицу, используя messageId
как часть запроса, так как это ключ раздела. Таким образом, вы не сможете запросить, просто room
а также userId
, То, что вы, вероятно, хотите, это глобальные вторичные индексы. В этом случае это будет работать:
MessagesDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: messageId
AttributeType: S
- AttributeName: room
AttributeType: S
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: messageId
KeyType: HASH
GlobalSecondaryIndexes:
- IndexName: roomIndex
KeySchema:
- AttributeName: room
KeyType: HASH
Projection:
ProjectionType: KEYS_ONLY
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
- IndexName: userIndex
KeySchema:
- AttributeName: userId
KeyType: HASH
Projection:
ProjectionType: KEYS_ONLY
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:custom.tableName}
Обратите внимание, что делает ваш ProjectionType: KEYS_ONLY
значит, когда вы запрашиваете roomIndex
или же userIndex
то, что вы получите обратно, просто messageIds
- тогда вам придется запросить таблицу с messageIds
чтобы получить другие атрибуты. Вы можете использовать другой ProjectionType
в зависимости от того, какой у вас шаблон использования.