首页 > 解决方案 > DynamoDB:当您知道分区键但不知道排序键时,如何使用 GSI 进行查询?

问题描述

我的桌子是这样设置的

 PK  |  SK  | CreatedAt (DateTime)(Secondary Global Index) | Random Attributes
USER | 0xFF | Today                                        | 1
USER | 0xFE | Yesterday                                    | 2

所以我的分区键是对象的通用组名。“用户”只是告诉我它是一个用户对象。稍后我将有“ITEM”或其他随机对象,或对象之间的链接以进行快速查询。排序键是随机生成的用户的实际 ID(uuid)。二级全局索引是“CreatedAt”,它是一个 DateTime 对象。

我只想找到最新的用户(我只关心SK)。

我试过这个;

QueryRequest qr = new QueryRequest
{
    TableName = "mytable",
    IndexName = "CreatedAt-index",
    ScanIndexForward = true,
    KeyConditionExpression = "PK = :v_pk",
    FilterExpression = "CreatedAt BETWEEN :v_timeOldest AND :v_timeNow",
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":v_pk", new AttributeValue{S = "USER" } },
        {":v_timeNow", new AttributeValue{S = DateTime.Now.ToString(AWSSDKUtils.ISO8601DateFormat)} },
        {":v_timeOldest", new AttributeValue{S = DateTime.Now.AddYears(-1).ToString(AWSSDKUtils.ISO8601DateFormat)} }
    },
    Limit = 1
};

QueryResponse res = await _client.QueryAsync(qr);

错误是;

Query key condition not supported

我认为这是因为它希望 CreatedAt 成为分区键,并且它必须是唯一的,因此不能进行 BETWEEN 比较。但这对这种情况没有用,因为许多对象的日期重复,而且它可以在其他日期之间。

我尝试了另一种方式,其中 KeyCondition 是 CreatedAt 语句,FilterExpression 是 PK 但同样的错误。

我期望的是仅使用分区键“USER”收集所有对象,然后根据 GSI 分区键进行升序/降序排序,然后选择列表顶部的那个。

我在这里想念什么?我对 GSI 的理解在概念上是否存在缺陷?

标签: c#amazon-web-servicesamazon-dynamodbpartitionsecondary-indexes

解决方案


从文档中KeyConditionExpression

您必须将分区键名称和值指定为相等条件。您可以选择为排序键(如果存在)提供第二个条件。

在此特定查询中,您尝试查询CreatedAt-index索引并PKKeyConditionExpression. 但是,您的索引用CreatedAt作主键,而不是名为 的属性PK。你说

我尝试了另一种方式,其中 KeyCondition 是 CreatedAt 语句,FilterExpression 是 PK 但同样的错误。

您没有显示查询,但听起来您这样做了

    ...
    KeyConditionExpression = "CreatedAt BETWEEN :v_timeOldest AND :v_timeNow",
    FilterExpression = "PK = :v_pk",
    ...

这将不起作用,因为(来自文档)您必须将分区键名称和值指定为相等条件。换句话说,您不能对分区键进行范围查询。

您没有展示如何定义二级索引,但听起来您已经定义了一个分区键,使用createdAt索引上没有排序键。从逻辑上讲,这看起来像这样:

在此处输入图像描述

这对您没有多大帮助,因为您无法对分区键执行范围查询。

但是,如果您要使用分区键 USER 和排序键createdAt. 该索引看起来像这样

二级索引

该索引将允许您按照您的描述执行查询操作。

顺便说一句,您描述的基表听起来不是很有用。您将所有用户存储在一个分区中,并将 UUID 作为排序键。UUID 的排序顺序听起来对您的应用程序不是特别有用。您可能需要为您的用户 ID 考虑 KSUID。KSUID 具有唯一性(如 UUID)可按创建时间排序的有用特性。当您需要唯一标识符需要按创建日期对它们进行排序时,这特别有用。


推荐阅读