在GSI上的DynamoDB之间查询无法按预期工作

时间:2019-11-11 07:00:42

标签: amazon-web-services nosql amazon-dynamodb dynamodb-queries

这是一个 jobPosts 架构,具有一个发布日期作为属性之一。目的是查询两个日期之间的所有职位。 这是供您参考的架构:

{
  'job_id': {S: jobInfo.job_id},
  'company': {S: jobInfo.company},
  'title': {S: jobInfo.title},
  'posted_on': {S: jobInfo.posted_on},
}

posted_on'基于ISO字符串(2019-11-10T10:52:38.013Z)。 job_id 是主键(分区键),由于我需要查询日期,因此我在 posted_on 上创建了 GSI partition key) >。现在是查询:

  const params = {
    TableName : "jobPosts",
    IndexName: 'date_for_filter_purpose-index',
    ProjectionExpression:"job_id, company, title, posted_on",
    KeyConditionExpression: "posted_on BETWEEN :startDate AND :endDate",
    ExpressionAttributeValues: {
        ":startDate": {S: "2019-10-10T10:52:38.013Z"},
        ":endDate": {S: "2019-11-10T10:52:38.013Z"}
    }
  };

我在dynamoDB中有一个文档,这里是:

{
  job_id:,
  company: "xyz",
  title: "abc",
  posted_on: "2019-11-01T10:52:38.013Z"
} 

现在,执行此操作时,出现以下错误:

{
    "message": "Query key condition not supported",
    "code": "ValidationException",
    "time": "2019-11-11T06:15:37.231Z",
    "requestId": "J078NON3L8KSJE5E8I3IP9N0IBVV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 12.382362030893768
}

我不知道上面的查询出了什么问题。

汤米回答后更新: 我在 posted_on 上删除了GSI,并重新创建了表,其中 job_id partition key,而 posted_on sort key。我收到以下错误:

{
    "message": "Query condition missed key schema element: job_id",
    "code": "ValidationException",
    "time": "2019-11-12T11:01:48.682Z",
    "requestId": "M9E793UQNJHPN5ULQFJI2NR0BVVV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 42.52613025785952
}

根据this SO answer GSI 应该能够使用 BETWEEN 关键字查询日期。

2 个答案:

答案 0 :(得分:1)

我想这有点违反直觉,但是DynamoDB在分区键属性上仅支持.eq条件。

按照KeyConditions Documentation

  

您必须提供索引分区键名称和值作为EQ条件。您可以选择提供第二个条件,引用索引排序键。

此外,在Query API Documentation中,您可以找到以下内容

  

该条件必须对单个分区键值执行相等性测试。

     

该条件可以选择对单个排序键值执行多个比较测试之一。这使Query可以检索具有给定分区键值和排序键值的一项,或者检索具有相同分区键值但排序键值不同的几项。

这说明了您收到的错误消息。

解决方案之一可能是创建一个具有posted_on属性作为排序键的复合主键,而不是GSI。然后,根据您的用例和访问模式,您需要确定哪个属性最适合作为分区键。

This blog应该可以帮助您为架构选择正确的分区键。

答案 1 :(得分:1)

answer you refer to与查询有关,其中分区键具有特定值,而排序键在给定范围内。与select * from table where status=Z and date between X and Y类似。如果我正确阅读了您的问题,那不是您要尝试做的事情。您需要select * from table where date between X and Y。您无法使用DynamoDB查询执行此操作-您无法按范围查询分区键。

如果您知道最大查询日期范围是在给定的日期,则可以创建一个GSI,并将分区键设置为计算出的日期/时间的YYYYMMDD值,并且其排序键是完整的约会时间。然后,您可以使用键条件表达式查询计算出的YYYYMMDD的分区键以及X和Y之间的排序键。要使此键有效,X和Y的YYYYMMDD必须相同。

如果您知道最大查询日期范围是一个月,则可以创建一个GSI,其分区键设置为计算出的日期/时间的YYYYMM,其排序键是完整的日期/时间。为此,X和Y的YYYYMM必须相同。