DynamoDB 如何设计和查询多个字段

Har*_*rts 2 database database-design nosql amazon-dynamodb dynamodb-queries

我有一个这样的项目

{
  "date": "2019-10-05",
  "id": "2",
  "serviceId": "1",
  "time": {
    "endTime": "1300",
    "startTime": "1330"
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我的设计方式是这样的:

primary key --> id
Global secondary index --> primary key : serviceId
                       --> sort key : date
Run Code Online (Sandbox Code Playgroud)

按照我现在的设计方式,

* I can query the id
* I can query serviceId and range of date
Run Code Online (Sandbox Code Playgroud)

我希望能够查询以便检索所有项目

* serviceId = 1 AND
* date = "yyyy-mm-dd" AND
* time = {
           "endTime": "1300",
           "startTime": "1330"
         }
Run Code Online (Sandbox Code Playgroud)

我仍然希望能够根据前面的 2 个条件进行查询(按 id 查询,以及按 serviceId 和 rangeOfDate 查询

有没有办法做到这一点?我想的一种方法是创建一个新字段并将其用作索引,例如:合并所有数据,以便合并字段:“1_yyyy-mm-dd_1300_1330

将其作为全局二级索引的主键,然后像这样查询它。

我只是不确定这是否是这样做的方法,或者是否有更好或最佳实践的方法来做到这一点?

谢谢

Har*_*air 5

您可以使用 FilterExpression 或复合排序键。

过滤表达式

在这里,您可以通过指定“serviceId”和“date”从您描述的 GSI 中检索项目,然后在“FilterExpression”中指定 time.startTime 和 time.endTime。使用 boto3 的示例 Python 代码如下:

response = table.query(
    KeyConditionExpression=Key('serviceId').eq(1) & Key('date').eq("2019-10-05"),
    FilterExpression=Attr(time.endTime).eq('1300') & Attr('time.startTime').eq('1330')
)
Run Code Online (Sandbox Code Playgroud)

此方法的缺点是,将读取使用排序键指定的所有项目,然后才过滤结果。因此,您将根据排序键中指定的内容付费。

例如:如果 1000 个项目的“serviceId”为 1,“date”为“2019-10-05”,但只有 10 个项目的“time.startTime”为 1330,那么您仍然需要为读取 1000 个项目付费,即使仅应用 FilterExpression 后将返回 10 个项目。

复合排序键

我相信这就是您在问题中提到的方法。在这里您需要将属性设置为

'yyyy-mm-dd_startTime_endTime'

并将其用作 GSI 中的排序键。现在您的项目将如下所示:

{   "date": "2019-10-05",
    "id": "2",
    "serviceId": "1",
    "time": {
        "endTime": "1300",
        "startTime": "1330"
    }
    "date_time":"2019-10-05_1330_1300"
}
Run Code Online (Sandbox Code Playgroud)

您的 GSI 将使用“serviceId”作为分区键,使用“date_time”作为排序键。现在您将能够查询日期范围:

response = table.query(
    KeyConditionExpression=Key('serviceId').eq(1) & Key('date').between('2019-07-05','2019-10-05')
)
Run Code Online (Sandbox Code Playgroud)

对于指定日期、开始和结束时间的查询,您可以查询为:

response = table.query(
    KeyConditionExpression=Key('serviceId').eq(1) & Key('date').eq('2019-10-05_1330_1300')
)
Run Code Online (Sandbox Code Playgroud)

如果您需要日期范围以及开始和结束时间,则此方法将不起作用。您将无法查询包含特定开始和结束时间的特定日期范围内的项目。在这种情况下,您将必须使用 FilterExpression。