问题描述
我一直在四处走动,但不清楚该怎么做.
I've been going around and around this and it's just not clear what to do.
我有一个简单的表,我想在其中对几列进行查询.据我了解,这意味着为要查询的每一列创建二级索引.我已经使用Serverless框架 serverless.yml
定义了表格,并收到各种奇怪的错误消息.
I have a simple table where I want to make queries against several columns. As I understand it, that means creating a secondary index for each column there is to query against. I've defined the table -- using the Serverless framework serverless.yml
-- and am getting a variety of strange error messages.
当前的 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服务-因此我想查询房间,用户等的条目.
It's meant to be something like a Slack service - and therefore I want to query for entries from a room, by a user, and so forth.
根据我已经找到的文档,此定义很有意义.我们应该为索引中使用的列声明属性,而我已经这样做了.KeySchema-我实际上只需要messageId字段,但是错误消息表明它需要RANGE索引,因此我将userId字段添加到KeySchema中只是为了关闭它.根据我已经找到的文档,二级索引字段看起来正确.
This definition makes sense going by the documentation I've been able to find. One is supposed to declare Attributes for the columns used in indexes, and I've done so. The KeySchema - I really only need the messageId field, but an error message indicated it needed a RANGE index, so I added the userId field to the KeySchema just to shut that up. The secondary index fields look right based on the documentation I've been able to find.
使用此定义,尝试使用 lessserver deploy
With this definition I'm getting this error when trying to deploy using serverless deploy
An error occurred: MessagesDynamoDBTable - Property AttributeDefinitions is inconsistent
with the KeySchema of the table and the secondary indexes.
我尝试了几种变体,还遇到了其他奇怪的错误.以下是一些内容,但我不记得对定义进行了相应的更改.
I have tried several variations and gotten other strange errors as well. What follows is a few, but I don't remember what the corresponding changes were to the definition.
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).
推荐答案
不起作用的原因是,本地二级索引中的键必须具有与表相同的分区键.因此,在您的情况下,您的本地二级索引必须将 messageId
作为其 HASH
键,并将 room
和 userId
作为 RANGE 键.并且由于您的表已经由(messageId,userId)
键控,因此您不需要 userId
本地二级索引.
The reason it isn't working is that the keys in a Local Secondary Index must have the same partition key as the table. So in your case, your Local Secondary Indexes must have messageId
as its HASH
key and room
and userId
as RANGE
keys on their respective indexes. And since your table is already keyed by (messageId, userId)
then you don't need the userId
Local Secondary Index.
此设置在技术上可以正常工作:
This setup would technically work:
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
进行查询.您可能想要的是全球二级索引.在这种情况下,这将起作用:
However if what you want to do is query by rooms and users, then you probably want to go with a different table design. What you are trying to do would end up requiring you to always query the table using the messageId
as part of the query since it is the partition key. So you wouldn't be able to query by just room
and userId
. What you probably want are Global Secondary Indexes. In that case, this would work:
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
.
Note that making your ProjectionType: KEYS_ONLY
means when you query roomIndex
or userIndex
what you would get back is just messageIds
- you would then have to requery the table with the messageIds
to get other attributes. You might want to use a different ProjectionType
depending on what your usage pattern is.
这篇关于DynamoDB查询二级索引,如何定义索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!