开始日期结束日期范围查询的Dynamodb模型数据

时间:2019-08-09 07:52:53

标签: amazon-dynamodb dynamodb-queries

我的问题可能与以下问题类似
How to query for an entry that falls between start and end date - DynamoDB
但是我认为我的要求和所寻找的有所不同。

对于特定的分区键值,我想查询当前日期在开始日期和结束日期之间的所有记录。

我的用例是将创建调查。每个调查都有一个名称,并且属于一个类别。每个调查都有一个开始日期和结束日期。我需要查询给定类别的所有活动调查的名称,即一个类别的所有调查,其当前日期位于开始日期和结束日期之间。此外,调查可能是有效/无效。

到目前为止已完成的工作:
表格设计:表格tbl_surveys
分区键:tbl_pk_surv
排序键:tbl_sk_surv
一个“数据”属性:data_attr

我创建了一个 GSI ,其中 tbl_sk_surv作为分区键,而 data_attr作为Sortkey

我为每个调查创建2条记录:
tbl_pk_surv |tbl_sk_surv|data_attr|cat_name|start_date|end_date|status Surv-0tOrClRnTz| SURVEY | Survey1 | Cat1 |1564012800|1564876799|1
tbl_pk_surv | tbl_sk_surv | data_attr| survey_name | status Surv-0tOrClRnTz | Cat1 | 1564012800-1564876799 | Survey1 | 1

因此,我将开始日期和结束日期放在第二条记录的1列中。我的计划是,我要查询GSI分区键值“ Cat1”,并获取“ Cat1”的所有测量名称。请让我知道如何查询GSI排序键值1564012800-1564876799,以便我可以在开始日期到结束日期之间进行查询。

请注意,我放置了第一条记录,其中静态值“ SURVEY”作为pk_sk_surv属性的值,这样我可以通过以“ SURVEY”作为分区键值查询GSI来查询所有调查记录。我正在尝试实现单表无SQL设计。

我是NoSql Design的新手,请指导我如何建模数据和查询我的需求。

1 个答案:

答案 0 :(得分:1)

如果我正确理解,您的记录将同时具有开始日期和结束日期(即您有时间间隔),并且您希望查询返回跨越特定值的记录(即开始日期小于输入值和结束日期大于输入值),那么答案是DynamoDB不直接支持该类型的查询。我的意思是,您必须在查询之上应用过滤器。过滤仍由Dynamo进行,但将在执行查询之后并将结果返回给您之前完成。

在最普通的情况下,可以使用任意时间编写查询,以获取所有在查询时间之前开始的调查,并过滤掉在查询时间之前也已结束的不需要的调查。

但是您的情况是一个特例,因为大概大多数调查将在查询时间之前开始和结束,因此在当前时间之后结束的唯一可能有害的结果将是计划的但尚未开始的调查。在这种情况下,您将编写查询以获取所有结束日期都在查询时间之后的调查,并过滤掉任何不需要的调查,调查数量不应该那么多。

如果您知道调查可以运行的最长时间(例如1个月),则可以通过设置结束日期的上限来进一步优化此查询。然后,您可以查询在查询日期和查询日期+上限之间结束的所有调查,然后应用过滤器。它仍然必须过滤掉一些结果,但是取决于上限的严格程度,它可能非常有效。

要实现此目的,您需要将分区键设置为“ category”属性,将排序键设置为“ endDate”,并使用单独的属性“ startDate”代表开始日期。

查询将如下所示(以Javascript为例):

  // assume the following are your input variable
  var search_category = 'some category name';
  var current_time = new Date().getTime() / 1000;  // current time epoch
  var max_time = current_time + 3600 * 24 * 31; // set upper bound to +1 month

  var docClient = new AWS.DynamoDB.DocumentClient();
  var result = await docClient.query({
     TableName : "SurveysTable",
     KeyConditionExpression: "#cat = :cat and #end between :ltime and :htime",
     FilterExpression: "#start < :ltime",
     ExpressionAttributeNames:{
        "#cat": "category",
        "#start": "startDate",
        "#end": "endDate"
     },
     ExpressionAttributeValues: {
        ":cat": search_category,
        ":ltime": current_time,
        ":htime": max_time
     }
  }).promise();
  // don't forget to handle pagination