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

问题描述 投票:0回答:2

我有这样的物品

{
  "date": "2019-10-05",
  "id": "2",
  "serviceId": "1",
  "time": {
    "endTime": "1300",
    "startTime": "1330"
  }
}

现在,我的设计方式如下:

primary key --> id
Global secondary index --> primary key : serviceId
                       --> sort key : date

以我目前的设计方式,

* I can query the id
* I can query serviceId and range of date

我希望能够进行查询,以便可以在其中检索所有项目

* serviceId = 1 AND
* date = "yyyy-mm-dd" AND
* time = {
           "endTime": "1300",
           "startTime": "1330"
         }

我仍然希望能够根据先前的2个条件进行查询(按ID查询,并按serviceId和rangeOfDate查询

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

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

我只是不确定这是这样做的方法,还是有更好或最佳实践的方法?

谢谢

database database-design nosql amazon-dynamodb dynamodb-queries
2个回答
0
投票

是的,您建议的解决方案(添加一个新字段,该字段是字段的组合并在其上定义了GSI)是实现此目的的标准方法。您需要确保用于连接的字符是唯一的,即,它不能出现在您组合的任何单个字段中。


0
投票

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

FilterExpression

在这里,您可以通过指定'serviceId'和'date',然后在'FilterExpression'中指定time.startTime和time.endTime,从您描述的GSI中检索项目。使用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')
)

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

例如:如果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"
}

您的GSI将以“ serviceId”作为分区键,并以“ date_time”作为排序键。现在,您可以查询日期范围为:

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.