如何使用非主键字段查询 DynamoDB?

How do I query DynamoDB with non primary key field?

我的 dynamoDB 中有以下数据 table。

这是我的代码:

const userStatusParams = {
        TableName: process.env.USERSTATUS_TABLE,
        KeyConditionExpression: "loggedIn = :loggedIn",
        ExpressionAttributeValues: {
          ":loggedIn": true
        }
      };
      var usersResult;
      try {
        usersResult = await dynamoDbLib.call("query", userStatusParams);
        console.log(usersResult);
      }catch (e) {
        console.log("Error occurred querying for users belong to group.");
        console.log(e);
      }

亚马逊 return 返回此错误:

{ ValidationException: Query condition missed key schema element: userId
    at Request.extractError ...

我如何获得 return loggedIn == true 的所有记录?

我的数据库目前通过我的 serverless.yml 配置结构如下。

phoneNumberTable: #This table is used to track phone numbers used in the system.
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:custom.phoneNumberTable}
        AttributeDefinitions: #UserID in this case will be created once and constantly updated as it changes with status regarding the user.
          - AttributeName: phoneNumber
            AttributeType: S
        KeySchema:
          - AttributeName: phoneNumber
            KeyType: HASH
        ProvisionedThroughput:
            ReadCapacityUnits: ${self:custom.dynamoDbCapacityUnits.${self:custom.pstage}}
            WriteCapacityUnits: ${self:custom.dynamoDbCapacityUnits.${self:custom.pstage}}

我通过其他答案对此进行了一些研究,但无法弄清楚我的情况。在其他答案中,他们有排序键,但我在这里不使用排序键。

为了查询 DynamoDB table,您只能查询属于主键或索引一部分的属性。

主键可以是:

  1. Partition/Hash 键,或
  2. Partition/Hash 键和一个 Sort/Range 键

除了Primary Key,还可以创建两种类型的索引:

  1. 本地二级索引,其中使用相同的分区键但具有不同的排序键,或者
  2. 全局二级索引,其中分区键和排序键都不同。

为了查询登录记录,您需要在主键中包含此属性,或者添加包含登录属性的本地或全局二级索引。

如果你正在做 query 那么你必须传递主键,在你的情况下是 userId。如果您没有 primaryKey 并且想要所有 logged in = true 字段,那么您可以像这样 filterExpressionscan

const userStatusParams = {
        TableName: process.env.USERSTATUS_TABLE,
        FilterExpression: 'loggedIn = :loggedIn',
        ExpressionAttributeValues: {
          ":loggedIn": true
        }
      };
      var usersResult;
      try {
        // Do scan
        usersResult = await dynamoDbLib.call("scan", userStatusParams);
        console.log(usersResult);
      }catch (e) {
        console.log("Error occurred querying for users belong to group.");
        console.log(e);
      }

更新: 由于scan操作效率较低,解决这个问题的另一种方法是创建一个GSI,主键loggedIn。但是这里的问题是你不能创建任何具有 boolean data type. 的字段主键。它必须是 number, string, binary。因此,要创建 gsi,您需要将接受的数据类型存储在 loggedIn 字段中,而不是 boolean

虽然我不确定它会对 table 千条记录产生多大的性能影响,但 gsi 的好处是您可以创建它们 later even on the existing table 如果未来你会发现一些性能影响。此外,您可以在 table 上创建的 gsi 数量限制为 5。所以明智地利用 gsi

扫描操作始终扫描整个 table 或二级索引,然后过滤掉值以提供所需的结果,本质上是添加从结果集中删除数据的额外步骤。如果可能,请避免对大型 table 或带有删除许多结果的过滤器的索引使用扫描操作。 Read more

你应该使用全局二级索引!

AWS 控制台 > DynamoDb > table 的选项卡索引 > 创建索引 >

primary key - loggedIn
secondary key - userId
projected attributes - all

我们应该添加辅助键以获得唯一的对。不要使用索引名称 (loggedIn),因为 loggedIn 应该是唯一的。

你可以使用带有主键的查询方法 (loggedIn)