如何在 DynamoDB 中查询和排序两个单独的排序键?
How to query and order on two separate sort keys in DynamoDB?
GROUPS
userID: string
groupID: string
lastActive: number
birthday: number
假设我有一个名为 GROUPS 的 DynamoDB table,它存储具有这些属性的项目。 table 记录哪些用户加入了哪些组。用户可以同时在多个组中。因此,复合主键最常见的是:
partition key: userID
sort key: groupID
但是,如果我想查询特定组中的所有用户,在特定生日范围内,按 lastActive
排序,这可能吗?如果可以,我需要什么索引要创建?
我可以合成 lastActive
和 userID
来创建合成排序键,如下所示:
GROUPS
groupID: string
lastActiveUserID: string (i.e. "20201230T09:45:59-abc123")
birthday: number
这将创建一个不同的复合主键,其中分区键为 groupID
,排序键为 lastActiveUserID
,这将根据参与者上次活动的时间对参与者进行排序,然后按生日过滤的二级索引?
正如所写,不,这是不可能的。
within a specific birthday range
意味着sk_birthday between :start and :end
sorted by lastActive
将 lastActive 隐含为排序键。
它们是互斥的...我无法设计能够以可用格式包含这两个值的排序键。
您可以使用散列键 group-id
和 lastActive
作为排序键的全局二级索引,然后按生日进行过滤。但是,这只会影响返回的数据,不会影响读取的数据,也不会影响读取该数据的成本。此外,由于 DDB 一次只能读取 1MB 的数据,如果给定的组可能有超过 1MB 的成员,则必须在循环中重复调用它。
此外,当您的索引具有与 table 不同的分区(散列)键时,这就是全局二级索引 (GSI)。如果您的索引具有与 table 相同的分区键但排序键不同,则可以使用本地二级索引 (LSI)
来完成
但是对于任何给定的查询,您只能使用 table 或给定的索引。不能同时使用多个索引
说了这么多,“特定生日范围” 对您来说到底是什么意思?也许您可以拥有一个 GSI,其中散列键是 "group-id#birthday-period"
,排序键是 lastActive
例如,“给我下个月的 GROUPA 生日”
查询(hs = "GROUPA#NOVEMBER")
但如果您想要 11 月和 12 月,则必须进行两次查询并自行合并和排序结果。
有效且高效地使用 DDB 意味着避免 Scan()
并避免使用 filterExpressions
,您知道这会丢弃大量读取的数据。
GROUPS
userID: string
groupID: string
lastActive: number
birthday: number
假设我有一个名为 GROUPS 的 DynamoDB table,它存储具有这些属性的项目。 table 记录哪些用户加入了哪些组。用户可以同时在多个组中。因此,复合主键最常见的是:
partition key: userID
sort key: groupID
但是,如果我想查询特定组中的所有用户,在特定生日范围内,按 lastActive
排序,这可能吗?如果可以,我需要什么索引要创建?
我可以合成 lastActive
和 userID
来创建合成排序键,如下所示:
GROUPS
groupID: string
lastActiveUserID: string (i.e. "20201230T09:45:59-abc123")
birthday: number
这将创建一个不同的复合主键,其中分区键为 groupID
,排序键为 lastActiveUserID
,这将根据参与者上次活动的时间对参与者进行排序,然后按生日过滤的二级索引?
正如所写,不,这是不可能的。
within a specific birthday range
意味着sk_birthday between :start and :end
sorted by lastActive
将 lastActive 隐含为排序键。
它们是互斥的...我无法设计能够以可用格式包含这两个值的排序键。
您可以使用散列键 group-id
和 lastActive
作为排序键的全局二级索引,然后按生日进行过滤。但是,这只会影响返回的数据,不会影响读取的数据,也不会影响读取该数据的成本。此外,由于 DDB 一次只能读取 1MB 的数据,如果给定的组可能有超过 1MB 的成员,则必须在循环中重复调用它。
此外,当您的索引具有与 table 不同的分区(散列)键时,这就是全局二级索引 (GSI)。如果您的索引具有与 table 相同的分区键但排序键不同,则可以使用本地二级索引 (LSI)
来完成但是对于任何给定的查询,您只能使用 table 或给定的索引。不能同时使用多个索引
说了这么多,“特定生日范围” 对您来说到底是什么意思?也许您可以拥有一个 GSI,其中散列键是 "group-id#birthday-period"
,排序键是 lastActive
例如,“给我下个月的 GROUPA 生日”
查询(hs = "GROUPA#NOVEMBER")
但如果您想要 11 月和 12 月,则必须进行两次查询并自行合并和排序结果。
有效且高效地使用 DDB 意味着避免 Scan()
并避免使用 filterExpressions
,您知道这会丢弃大量读取的数据。