You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:03:12