GSI 上的 DynamoDB Between 查询无法按预期工作

DynamoDB Between query on GSI does not work as expected

它是一个 jobPosts 模式,其中一个属性是 posted_date。目标是查询两个日期之间的所有职位发布。 这是供您参考的架构:

{
  '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 是主键(分区键),因为我需要查询日期,所以我创建了 GSI(partition key) posted_on。现在这里是查询:

  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 重新创建了 table 作为 partition keyposted_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 answerGSI 应该能够使用 BETWEEN 关键字查询日期。

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

根据KeyConditions Documentation

You must provide the index partition key name and value as an EQ condition. You can optionally provide a second condition, referring to the index sort key.

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

The condition must perform an equality test on a single partition key value.

The condition can optionally perform one of several comparison tests on a single sort key value. This allows Query to retrieve one item with a given partition key value and sort key value, or several items that have the same partition key value but different sort key values.

这解释了您收到的错误消息。

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

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

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,并将分区键设置为 date/time 的计算 YYYYMMDD 值及其排序关键是完整的 date/time。然后,您可以使用键条件表达式查询计算出的 YYYYMMDD 的分区键以及 X 和 Y 之间的排序键。为此,X 和 Y 的 YYYYMMDD 必须相同。

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