Dynamodb 稀疏索引实现
Dynamodb sparse indexes implementation
我是 dynamodb 的新手,遇到了 sparse indexes。我认为它们适合我的需要,但我不完全确定如何实施它们。在我的例子中,我有一个 table 和一个 Post 实体,它有以下字段,它看起来像这样:
post_id <string> | user_id <string> | tags <string[]> | public <boolean>| other post data attributes...
我需要做的查询是:
- 获取所有标记为public
的post
- 获取 posts 按标签筛选
- 获取所有 post 由用户过滤,包括 public 和不 public
- 获得一个post
对于获取所有 public post 的情况,我认为 稀疏索引 可以工作。我只能将 public 属性设置为标有 public 的实体。但是,查询看起来像什么?
我什至不确定我是否正确设置了数据库。我正在使用无服务器框架,这是我想出的,但不确定它是否好。
PostsDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: postId
AttributeType: S
- AttributeName: userId
AttributeType: S
- AttributeName: createdAt
AttributeType: S
KeySchema:
- AttributeName: postId
KeyType: HASH
- AttributeName: userId
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
TableName: ${self:provider.environment.POSTS_TABLE}
GlobalSecondaryIndexes:
- IndexName: ${self:provider.environment.USER_ID_INDEX}
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: public
KeyType: RANGE
Projection:
ProjectionType: ALL
稀疏索引可以工作如果您只想要属性的一个子集,您会想要使用ProjectionType: INCLUDES
将non-key属性包含到稀疏索引(在你的例子中:public 属性)。请务必注意,在对稀疏索引的查询中您可以访问的唯一属性是您显式包含的属性。
首先,您需要在属性定义中声明那些 public 属性。
例如,public 属性之一是 userName
。
您要添加:
- AttributeName: userName
AttributeType: S
然后,在 GlobalSecondaryIndexes
块中:
GlobalSecondaryIndexes:
- IndexName: byUserIdAndPublic // You can name this whatever you'd like
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: public
KeyType: RANGE
Projection:
NonKeyAttributes:
- userName
ProjectionType: INCLUDE
然后您只需专门查询该索引 - 在响应中,您将取回用户名(不需要特殊的查询更改,除非指定使用该索引)。
如果每个 post 都需要 all 属性,则需要使用 ProjectionType: ALL
,(然后只需删除 NonKeyAttributes
位)
这是一个示例 nodejs 方法,它将通过 public 过滤 posts(public 是传递给该方法的布尔值):
const listByUserIdAndPublic = async (userId, public) => {
const params = {
TableName: tableName,
IndexName: 'byUserIdAndPublic',
KeyConditionExpression: '#public = :public AND #userId = :userId',
ExpressionAttributeNames: {
'#userId': 'userId',
'#public': 'public'
},
ExpressionAttributeValues: {
':public': public,
':userId': userId
},
};
const response = await documentClient.query(params).promise();
return response.Items;
};
根据您的问题:
Get all posts that are marked public
我想你会想要使用完整索引 (ProjectionType: ALL
),因为我想你希望 post 的所有属性都被索引。
我是 dynamodb 的新手,遇到了 sparse indexes。我认为它们适合我的需要,但我不完全确定如何实施它们。在我的例子中,我有一个 table 和一个 Post 实体,它有以下字段,它看起来像这样:
post_id <string> | user_id <string> | tags <string[]> | public <boolean>| other post data attributes...
我需要做的查询是:
- 获取所有标记为public 的post
- 获取 posts 按标签筛选
- 获取所有 post 由用户过滤,包括 public 和不 public
- 获得一个post
对于获取所有 public post 的情况,我认为 稀疏索引 可以工作。我只能将 public 属性设置为标有 public 的实体。但是,查询看起来像什么?
我什至不确定我是否正确设置了数据库。我正在使用无服务器框架,这是我想出的,但不确定它是否好。
PostsDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: postId
AttributeType: S
- AttributeName: userId
AttributeType: S
- AttributeName: createdAt
AttributeType: S
KeySchema:
- AttributeName: postId
KeyType: HASH
- AttributeName: userId
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
TableName: ${self:provider.environment.POSTS_TABLE}
GlobalSecondaryIndexes:
- IndexName: ${self:provider.environment.USER_ID_INDEX}
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: public
KeyType: RANGE
Projection:
ProjectionType: ALL
稀疏索引可以工作如果您只想要属性的一个子集,您会想要使用ProjectionType: INCLUDES
将non-key属性包含到稀疏索引(在你的例子中:public 属性)。请务必注意,在对稀疏索引的查询中您可以访问的唯一属性是您显式包含的属性。
首先,您需要在属性定义中声明那些 public 属性。
例如,public 属性之一是 userName
。
您要添加:
- AttributeName: userName
AttributeType: S
然后,在 GlobalSecondaryIndexes
块中:
GlobalSecondaryIndexes:
- IndexName: byUserIdAndPublic // You can name this whatever you'd like
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: public
KeyType: RANGE
Projection:
NonKeyAttributes:
- userName
ProjectionType: INCLUDE
然后您只需专门查询该索引 - 在响应中,您将取回用户名(不需要特殊的查询更改,除非指定使用该索引)。
如果每个 post 都需要 all 属性,则需要使用 ProjectionType: ALL
,(然后只需删除 NonKeyAttributes
位)
这是一个示例 nodejs 方法,它将通过 public 过滤 posts(public 是传递给该方法的布尔值):
const listByUserIdAndPublic = async (userId, public) => {
const params = {
TableName: tableName,
IndexName: 'byUserIdAndPublic',
KeyConditionExpression: '#public = :public AND #userId = :userId',
ExpressionAttributeNames: {
'#userId': 'userId',
'#public': 'public'
},
ExpressionAttributeValues: {
':public': public,
':userId': userId
},
};
const response = await documentClient.query(params).promise();
return response.Items;
};
根据您的问题:
Get all posts that are marked public
我想你会想要使用完整索引 (ProjectionType: ALL
),因为我想你希望 post 的所有属性都被索引。