amazon-dynamodb - 开始日期结束日期范围查询的 Dynamodb 模型数据
问题描述
我的问题可能类似于以下问题
如何查询介于开始日期和结束日期之间的条目 - DynamoDB
,但我认为在我的要求和我正在寻找的内容方面有所不同。
对于特定的分区键值,我想查询当前日期位于开始日期和结束日期之间的所有记录。
我的用例是创建调查。每个调查都有一个名称并属于一个类别。每个调查都有一个开始日期和结束日期。我需要查询给定类别的所有活动调查的名称,即所有调查的类别,其当前日期位于开始日期和结束日期之间。此外,调查可以是活动/非活动的。
到目前为止做了什么:
表设计:表 tbl_surveys
分区键:tbl_pk_surv
排序键:tbl_sk_surv
一个“数据”属性:data_attr
我创建了一个GSI,其中tbl_sk_surv 作为 Partition Key,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
所以我把 startdate 和 enddate 放在第二条记录的 1 列中。我的计划是,我想查询 GSI 分区键值“Cat1”,并获取“Cat1”的所有调查名称。请让我知道如何查询 GSI 排序键值 1564012800-1564876799,以便我可以在开始日期-结束日期之间进行查询。
请注意,我放置了第一条记录,静态值“SURVEY”作为 pk_sk_surv 属性的值,这样我就可以查询所有调查记录,通过查询 GSI 以“SURVEY”作为分区键值。我正在尝试实现单表 no-sql 设计。
我是 NoSql 设计的新手,请指导我如何为我的需求建模数据和查询。
解决方案
如果我理解正确,您的记录将同时具有开始日期和结束日期(即您有一个时间间隔),并且您希望查询返回跨越特定值的记录(即开始日期小于输入值和结束日期大于输入值),那么答案是 DynamoDB 不直接支持该类型的查询。我的意思是您必须在查询之上应用过滤器。过滤仍由 Dynamo 完成,但将在查询执行后和结果返回给您之前完成。
在最一般的情况下,您可以编写一个查询,获取在查询时间之前开始的所有调查,并过滤掉在查询时间之前结束的不需要的调查。
但是您的情况是一个特殊情况,因为可能大多数调查会在查询时间之前开始和结束,因此在当前时间之后结束的唯一可能不需要的结果将是已安排但尚未开始的调查。在这种情况下,您将编写查询以获取结束日期在查询时间之后的所有调查,并过滤掉任何不需要的调查,这些调查不应该那么多。
如果您知道调查可以运行的最长期限(例如 1 个月),则可以通过设置结束日期的上限来进一步优化此查询。然后,您可以查询在查询日期和查询日期+上限之间结束的所有调查,然后应用过滤器。它仍然需要过滤掉一些结果,但取决于你的上限有多紧,它可能非常有效。
要实现这一点,您需要将分区键设置为“类别”属性,将排序键设置为“结束日期”,并使用单独的属性“开始日期”来表示开始日期。
查询将如下所示(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
推荐阅读
- reactjs - 将 JS 文件导入 Next JS - 出现引用错误
- python - pip freeze 显示所有库,而不是我的虚拟环境中的库
- python - selenium 或其他网络爬虫工具是否对于将数据从 chrome 抓取到 python 脚本是强制性的
- python - 如何检查倒序字符串元组并将它们从 python 文件中删除?
- nuget - 没有 Lib-Ref-Content 文件夹的 Nuget 包
- swift - 使用 Xcode/Swift,我如何使用 SF Symbol 作为资产中的标签栏图标?资产字段不接受 .svg 文件
- c# - 如何使用菜单、子菜单、子菜单、项目创建树节点
- spring - 如何使用 SSL 和 Spring Boot 连接到 PostgresQL?
- php - Laravel:为多租户应用程序的不同域使用不同的 env 文件
- mysql - 如何在 Knex.js 中获取多个插入的最后插入的 IDS?