C# DynamoDB:当您知道分区键而不知道排序键时,如何使用GSI进行查询?

C# DynamoDB:当您知道分区键而不知道排序键时,如何使用GSI进行查询?,c#,amazon-web-services,amazon-dynamodb,partition,secondary-indexes,C#,Amazon Web Services,Amazon Dynamodb,Partition,Secondary Indexes,我的桌子是这样摆的 PK | SK | CreatedAt (DateTime)(Secondary Global Index) | Random Attributes USER | 0xFF | Today | 1 USER | 0xFE | Yesterday | 2 因此,我的分区键是对象的通用组名。“用户”只是告诉我它是一个用户对

我的桌子是这样摆的

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

因此,我的分区键是对象的通用组名。“用户”只是告诉我它是一个用户对象。稍后,我将有“项目”或其他随机对象,或对象之间的快速查询链接。排序键是随机生成的用户的实际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);
我假设这是因为它期望CreatedAt是分区键,并且它需要是唯一的,所以不能进行比较。但是,由于许多对象的日期重复,而且可能在其他日期之间,因此这在这种情况下没有用处

我尝试了另一种方法,其中KeyCondition是CreatedAt语句,FilterExpression是PK,但错误相同

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


我错过了什么?我对GSI的理解在概念上有缺陷吗?

来自
KeyConditionExpression

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

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

我尝试了另一种方法,其中KeyCondition是CreatedAt语句,FilterExpression是PK,但错误相同

您没有显示查询,但听起来好像是这样做的

    ...
    KeyConditionExpression = "CreatedAt BETWEEN :v_timeOldest AND :v_timeNow",
    FilterExpression = "PK = :v_pk",
    ...
这将不起作用,因为(从文档中)必须将分区键名称和值指定为相等条件。换句话说,您不能对分区键执行范围查询

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

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

但是,如果要定义一个二级索引,分区键为USER,排序键为
createdAt
。该索引将如下所示

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

此索引将允许您执行所描述的查询操作


另一方面,您描述的基表听起来不是很有用。您正在使用UUID作为排序键将所有用户存储在单个分区中。UUID的排序顺序听起来对应用程序不是特别有用。您可能想为用户ID考虑KUIDID。ksuid具有独特(如UUID)和可按创建时间排序的有用特性。当您需要一个唯一的标识符,并且需要按创建日期对其进行排序时,这一点特别有用。

不了解KSUIDs,非常感谢。