如何使用Scanamo在Local DynamoDB中创建多个GSI
使用Scanamo v1.0.0-M23创建多GSI的DynamoDB表
核心思路
LocalDynamoDB.createTableWithIndex仅支持单个全局二级索引,要创建多个GSI,需要手动构建CreateTableRequest,结合Scanamo的TableSchema生成基础表结构后,追加多个GSI的定义,最后通过Scanamo的客户端执行创建操作。
实现步骤与代码示例
1. 定义实体类与TableSchema
假设你的UnLocation实体类如下,先定义对应的Scanamo TableSchema:
import software.amazon.awssdk.services.dynamodb.model.{AttributeDefinition, KeySchemaElement, KeyType, ScalarAttributeType} import org.scanamo._ import org.scanamo.generic.auto._ case class UnLocation( pk: String, // 表的主键哈希键 sk: String, // 表的主键排序键 iata: String, id: String, name: String, region: String ) // 自动生成TableSchema implicit val unLocationSchema: TableSchema[UnLocation] = TableSchema.derive[UnLocation]
2. 构建基础表结构信息
从TableSchema中提取表的主键定义,同时收集所有GSI需要用到的属性定义:
// 表的主键Schema val tableKeySchema = unLocationSchema.primaryKey.map { case (name, KeyType.HASH) => KeySchemaElement.builder().attributeName(name).keyType(KeyType.HASH).build() case (name, KeyType.RANGE) => KeySchemaElement.builder().attributeName(name).keyType(KeyType.RANGE).build() } // 基础属性定义(表主键属性) val baseAttributeDefs = unLocationSchema.primaryKey.map { case (name, _) => AttributeDefinition.builder().attributeName(name).attributeType(ScalarAttributeType.S).build() } // GSI需要的额外属性定义 val gsiAttributeDefs = List( AttributeDefinition.builder().attributeName("iata").attributeType(ScalarAttributeType.S).build(), AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build(), AttributeDefinition.builder().attributeName("name").attributeType(ScalarAttributeType.S).build(), AttributeDefinition.builder().attributeName("region").attributeType(ScalarAttributeType.S).build() ) val allAttributeDefs = baseAttributeDefs ++ gsiAttributeDefs
3. 定义多个GSI
分别创建三个GSI的配置:
// GSI1: iata作为哈希键 val gsiIata = GlobalSecondaryIndex.builder() .indexName("iata-index") .keySchema(KeySchemaElement.builder().attributeName("iata").keyType(KeyType.HASH).build()) .projection(projection => projection.projectionType("ALL")) // 根据需求选择投影类型 .provisionedThroughput(throughput => throughput.readCapacityUnits(10L).writeCapacityUnits(10L)) .build() // GSI2: id作为哈希键 val gsiId = GlobalSecondaryIndex.builder() .indexName("id-index") .keySchema(KeySchemaElement.builder().attributeName("id").keyType(KeyType.HASH).build()) .projection(projection => projection.projectionType("ALL")) .provisionedThroughput(throughput => throughput.readCapacityUnits(10L).writeCapacityUnits(10L)) .build() // GSI3: name哈希键 + region排序键 val gsiNameRegion = GlobalSecondaryIndex.builder() .indexName("name-region-index") .keySchema( KeySchemaElement.builder().attributeName("name").keyType(KeyType.HASH).build(), KeySchemaElement.builder().attributeName("region").keyType(KeyType.RANGE).build() ) .projection(projection => projection.projectionType("ALL")) .provisionedThroughput(throughput => throughput.readCapacityUnits(10L).writeCapacityUnits(10L)) .build()
4. 组装并执行创建表请求
用Scanamo的客户端获取DynamoDB实例,构建完整的CreateTableRequest并执行:
import org.scanamo.DynamoDB import software.amazon.awssdk.services.dynamodb.DynamoDbClient // 初始化Local DynamoDB客户端 val localDynamoClient = DynamoDbClient.builder() .endpointOverride(java.net.URI.create("http://localhost:8000")) // 对应你的docker-compose端口 .region(software.amazon.awssdk.regions.Region.US_EAST_1) .build() val dynamoDB = DynamoDB(localDynamoClient) // 构建CreateTableRequest val createTableRequest = software.amazon.awssdk.services.dynamodb.model.CreateTableRequest.builder() .tableName("UnLocation") .keySchema(tableKeySchema: _*) .attributeDefinitions(allAttributeDefs: _*) .globalSecondaryIndexes(gsiIata, gsiId, gsiNameRegion) .provisionedThroughput(throughput => throughput.readCapacityUnits(10L).writeCapacityUnits(10L)) .build() // 执行创建表操作 dynamoDB.exec(createTableRequest)
关键注意事项
- 确保所有GSI用到的属性都被添加到
attributeDefinitions中,否则会触发验证错误。 - 根据实际业务需求调整GSI的投影类型(
ALL/KEYS_ONLY/INCLUDE)和读写容量单位。 - 如果使用按需模式,可以替换
provisionedThroughput为billingMode(BillingMode.PAY_PER_REQUEST)。
内容的提问来源于stack exchange,提问作者sentenza
相关产品推荐
相关产品推荐

