Terraform + DynamoDB:所有属性必须被索引

63

我想创建一个Terraform配置,用于拥有多个(> 10)属性的DynamoDB表。但我不需要将所有属性作为索引添加到global_secondary_indexlocal_secondary_index中。但是当我运行terraform plan命令时,出现了以下错误:

所有属性都必须被索引。未使用的属性:...

我在validateDynamoDbTableAttributes函数中发现了Terraform存储库中的验证检查。

但是,据我所知,最佳实践是:DynamoDB中的每个表最多限制为五个全局二级索引和五个本地二级索引。(参见DynamoDB中二级索引的一般准则)。

由于我的属性超过10个,这对我来说似乎是个问题。

我想了解为什么所有属性都必须被索引,如果有很多属性该怎么办。

谢谢!

3个回答

126

创建表时,您不必预先定义要使用的每个属性。

aws_dynamodb_table 资源内的 attribute 块并不是定义您可以在应用程序中使用哪些属性。它们是定义表和索引的键模式

例如,以下 Terraform 定义了一个仅具有哈希键的表:

resource "aws_dynamodb_table" "test" {
  name           = "test-table-name"
  read_capacity  = 10
  write_capacity = 10
  hash_key       = "Attribute1"

  attribute {
    name = "Attribute1"
    type = "S"
  }
}

这个表中的每个项目都有Attribute1,但您可以使用自己的应用程序创建附加属性。 两个项目,都具有Attribute1,但具有不同的自定义属性

这意味着只要您不需要在AttributeDefinition中定义它们,并且由于您说您不需要将其索引化,因此您可以拥有10多个属性。

有关混淆的讨论(attribute很令人困惑,与DynamoDB API不匹配),请参见此拉取请求


12
谢谢你强调这个 Terraform 代码块仅定义了“关键”属性。我也遇到了同样的问题,理解这个细节帮助我刚刚解决了自己的问题。 - Mass Dot Net
1
谢谢,这正是我所需要的。我对DynamoDB非常陌生,并且正在使用Terraform重新创建别人的表格。当我在编写我的terraform代码时,我想知道,这不应该是NoSQL吗?那么为什么我必须事先定义相当于SQL表模式的内容呢? - hyperwiser

6
我正在为一个 LSI 添加投影字段,并在投影字段中添加属性条目,这导致了错误。您只需将投影字段列在 non_key_attributes 中即可,如下所示。它不需要被定义为属性,因为它不是关键字。
local_secondary_index {
  name = "allocated_plus_created-lsi"
  range_key = "allocated_plus_created"
  projection_type = "INCLUDE"
  non_key_attributes = ["allocated"]
}

在TF中,Allocated不应该被定义为属性。


2
DynamoDB是一种无模式数据库,这意味着您在创建时不需要定义所有属性,但您需要非常明确地说明主要属性和索引。每个声明的属性都需要一个显式的索引,因此会出现错误“必须对所有属性进行索引”。
例如,下面的代码将要求任何新条目中都必须包含“电子邮件”和“时间戳”:
provider "aws" {
  region = var.region
}

module "dynamodb_table_1" {
  source              = "../../"
  name                = "Subscribed_Users"
  hash_key            = "Email"
  range_key           = "Timestamp"
  enable_autoscaler   = false
  dynamodb_attributes = [
    {
      name = "Email"
      type = "S"
    }
  ]

  local_secondary_index_map = [
    {
      name               = "EmailAndTimestampSortIndex"
      hash_key           = "Email"
      range_key          = "Timestamp"
      projection_type    = "INCLUDE"
      non_key_attributes = ["Email", "Timestamp"]
    },
  ]

  context = module.this.context
}

以下是两个有效的插入(因为它们都包含电子邮件和时间戳):

第一条记录

{
  "Email": {
    "S": "foo@foo.com"
  },
  "Timestamp": {
    "S": "Wed, 18 Jan 2023 01:45:40 GMT"
  },
  "Address": {
    "M": {
      "Country": {
        "S": "Australia"
      }
    }
  },
  "Name": {
    "S": "Melchor"
  }
}

第二项

{
      "Email": {
        "S": "foo2@foo.com"
      },
      "Timestamp": {
        "S": "Wed, 18 Jan 2023 01:45:40 GMT"
      },
      "Name": {
        "S": "Bob"
      }
}

插入的值: 输入图像描述

关于哈希和范围键的详细解释,请参见:https://dev59.com/gl4c5IYBdhLWcg3w-OQ4#27348364


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接