是否可以对DynamoDB中的查询结果或扫描进行ORDER结果?


Answers:


42

但是,未明确指出,对于许多实际使用案例而言,排序显然是必需的,并且可以相应地通过哈希和范围类型主键来建模:

在这种情况下,主键由两个属性组成。第一个属性是哈希属性,第二个属性是范围属性。Amazon DynamoDB在哈希主键属性上构建无序哈希索引,并在范围主键属性上构建排序范围索引[强调我的]

然后,可以使用该范围内的索引来可选地经由请求项RangeKeyCondition所述的参数查询API并指定向前或索引的向后遍历通过(即排序方向)ScanIndexForward参数。

更新:您可以通过具有本地二级索引的属性以相同的方式进行排序。


18
ScanIndexForward参数似乎仅适用于Query,而不适用于扫描正确吗?如何使用查询返回表中所有项目的分页列表?扫描似乎是返回“ *”的方式,但似乎没有排序结果的参数。
case2000

我没有使用此功能,只是阅读了此功能,但是Query支持指定Limit来限制接收到的结果的数量,并且如果达到限制时,如果有更多与您的查询匹配的项目,您将收到LastEvaluatedKey可用于执行其他查询并继续获取结果。
fernio 2014年

1
重要的陷阱:返回的结果实际上不会排序。仅当您应用“限制”值或项目数超过1MB查找限制时,排序才起作用。例如,您可能有5条记录,分区键为“ p1”,排序键为['b','d','a','c','e']。如果仅对“ p1”执行查询,则会收到['b','d','a','c','e']。但是,如果您将限制指定为2,它将返回['b','a']
jameslol

29

您可以使用排序键,并在查询中应用ScanIndexForward参数以升序或降序排序。在这里,我将项目限制为1。

var params = {
    TableName: 'Events',
    KeyConditionExpression: 'Organizer = :organizer',
    Limit: 1,
    ScanIndexForward: false,    // true = ascending, false = descending
    ExpressionAttributeValues: {
        ':organizer': organizer
    }
};

docClient.query(params, function(err, data) {
    if (err) {
        console.log(JSON.stringify(err, null, 2));
    } else {
        console.log(JSON.stringify(data, null, 2));
    }
});

8
问题是是否要退回所有物品。从本质上讲,这意味着您必须创建一个新的虚拟列,将相同的值分配给所有行,在该列上创建GSI,然后调用查询而不是扫描。
JHH'6

如果我想根据某些非关键字段返回该怎么办?像created_on数字字段一样
Yusuf

然后,您可能想要获取所有记录,然后使用javascript或类似过滤器过滤它们。DynamoDB本质上是功能有限的键值存储。但是使用钥匙时非常快。
kometen

7

使用ScanIndexForward(升序为true,降序为false),也可以使用查询表达式的setLimit值限制结果。

请在下面的代码中使用QueryPage查找单个记录。

public void fetchLatestEvents() {
    EventLogEntitySave entity = new EventLogEntitySave();
    entity.setId("1C6RR7JM0JS100037_contentManagementActionComplete");

    DynamoDBQueryExpression<EventLogEntitySave> queryExpression = new DynamoDBQueryExpression<EventLogEntitySave>().withHashKeyValues(entity);
    queryExpression.setScanIndexForward(false);
    queryExpression.withLimit(1);
    queryExpression.setLimit(1);

    List<EventLogEntitySave> result = dynamoDBMapper.queryPage(EventLogEntitySave.class, queryExpression).getResults();
    System.out.println("size of records = "+result.size() );
}

@DynamoDBTable(tableName = "PROD_EA_Test")
public class EventLogEntitySave {

        @DynamoDBHashKey
        private String id;
        private String reconciliationProcessId;
        private String vin;
        private String source;
}

public class DynamoDBConfig {
    @Bean
    public AmazonDynamoDB amazonDynamoDB() {

            String accesskey = "";
            String secretkey = "";
            //
            // creating dynamo client
            BasicAWSCredentials credentials = new BasicAWSCredentials(accesskey, secretkey);
            AmazonDynamoDB dynamo = new AmazonDynamoDBClient(credentials);
            dynamo.setRegion(Region.getRegion(Regions.US_WEST_2));
            return dynamo;
        }

    @Bean
    public DynamoDBMapper dynamoDBMapper() {
        return new DynamoDBMapper(amazonDynamoDB());
    }
}

使用ScanIndexForward(升序为true,降序为false)
ABHAY JOHRI

1

如果您使用的是boto2,并且在表中的某一列上具有排序键,则可以通过说以下顺序对检索到的内容进行排序:

result = users.query_2(
    account_type__eq='standard_user',
    reverse=True)

如果您使用的是boto3,并且您要对结果进行排序的列上具有排序键,则可以通过说出以下内容来对检索到的数据进行排序:

result = users.query(
    KeyConditionExpression=Key('account_type').eq('standard_user'),
    ScanIndexForward=True)

请记住,在boto3中,如果ScanIndexForward为true,则DynamoDB将按存储顺序(按排序键值)返回结果。这是默认行为。如果ScanIndexForward为false,则DynamoDB按排序键值以相反的顺序读取结果,然后将结果返回给客户端。


1

解决该问题的另一种方法是

  1. 还将带有“普通”哈希键的本地二级索引也定义为LSI的哈希键
  2. 将要排序的字段定义为LSI的“排序键”
  3. 查询LSI并根据需要设置顺序(请参见上文)

这将允许根据需要对表的任何值进行排序。这是一种非常有效的方法,它可以在表中查找排名最高的项目,而无需获取整个查询,然后对其进行过滤。


上面是什么?如果普通散列对于排序生成的ID是无序的,则包含它似乎无效。我想念什么吗?
萨曼莎·阿特金斯

0

如果该表已经存在,则将GSI(全局二级索引)添加到该表所需的属性中,并使用“查询”而不是“扫描”。如果要创建表,则可以将LSI(本地二级索引)添加到所需的属性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.