【问题标题】:How do I query DynamoDB with non primary key field?如何使用非主键字段查询 DynamoDB?
【发布时间】:2018-05-14 03:59:12
【问题描述】:

我的 dynamoDB 表中有以下数据。

这是我的代码:

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);
      }

亚马逊返回此错误:

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

如何让它返回所有已登录 == 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}}

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

【问题讨论】:

  • 如果你正在做query,那么你必须传递主键,在你的情况下是userId
  • 你的意思是电话号码?
  • 无论如何我在查询时都没有可用的主键
  • 如果你想要所有的logged in = true 字段,那么你必须使用scanfilterExpression
  • 我在这里创建了一个修改后的问题来进一步解决我的问题,stackoverflow.com/questions/47585581/…

标签: node.js amazon-web-services amazon-dynamodb serverless-framework


【解决方案1】:

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

主键可以是:

  1. 分区/哈希键,或
  2. 分区/哈希键和排序/范围键

除了主键,还可以创建两种索引:

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

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

【讨论】:

  • 这个答案不正确,DynamoDB 确实允许搜索非索引属性。搜索称为扫描。使用索引属性的搜索称为查询。
  • 扫描不是搜索。
【解决方案2】:

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

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

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

【讨论】:

  • 所以在我的情况下,由于这可能会增长到一千多个用户,我注意到其他一些用户建议使用二级索引。这种情况下扫描效果更好吗?
  • @JosephAstrahan 毫无疑问scan 的成本很高。检查更新的答案。如果你可以存储number/string 来代表loggedIn 字段,那么最好去:)
  • 谢谢,这个答案给了我很多灵活性和选择。
  • 你知道如何对字符串集进行过滤吗?像组,所以它只显示属于组默认的结果?
  • 想通了,对于其他人来说,FilterExpression:“loggedIn = :loggedIn and #s = :status and contains(#g,:group)”,当然还要加上这个,ExpressionAttributeNames: {“#s”:“状态”,“#g”:“组”}。我必须为状态和组执行此操作,因为它们是 DynamoDB 中的保留关键字
【解决方案3】:

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

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

AWS Console > DynamoDb > tab Indexes of your table > Create index >

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

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

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

【讨论】:

  • 这是我实际上要查询的 4 个值,登录、组、优先级以及状态和类型。这个表可能不会超过一千条记录。
  • 我在这里创建了一个问题来解释这一点,stackoverflow.com/questions/47585581/…
  • 我赞成你的问题。我不确定 dynamodb 是否可行。我建议在获取所有数据后过滤 lambda 中的数据..
  • 碰巧你知道如何访问至少在扫描中设置的组字符串吗?
猜你喜欢
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 2020-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多