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

时间:2012-02-15 16:36:57

标签: amazon-dynamodb

是否可以使用DynamoDB中的Query或Scan API对结果进行ORDER?

我需要知道DynamoDB是否有来自SQL查询的[ORDER BY'field']?

感谢。

7 个答案:

答案 0 :(得分:36)

然而,没有明确说明,许多现实世界的用例显然需要排序,并且可以通过Hash and Range Type Primary Key相应地建模:

  

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

然后,您可以使用此范围索引通过Query API RangeKeyCondition 参数选择性地请求项目,并指定索引的向前或向后遍历(即排序方向)通过 ScanIndexForward 参数。

更新:您可以按照local secondary index的属性以同样的方式订购。

答案 1 :(得分:18)

您可以使用sort-key并在query中应用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));
    }
});

答案 2 :(得分:6)

使用ScanIndexForward(true表示升序,false表示降序),也可以使用Query Expression的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());
    }
}

答案 3 :(得分: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)

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

答案 4 :(得分:1)

另一个可以解决该问题的方法是

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

我从没想到过如此琐碎的任务会在DynamoDB中变成问题。 Dynamo需要一些基本分区。我设法通过添加额外的列 status 来对数据进行排序,然后使用这两个字段创建GSI索引。我通过createdAt字段以status =“ active”排序数据。

创建GSI

{
        IndexName: "createdAt",
        KeySchema: [
            { AttributeName: "status", KeyType: "HASH" },
            { AttributeName: "createdAt", KeyType: "RANGE" }
        ],
        Projection: { ProjectionType: "ALL" },
        ProvisionedThroughput: {
          ReadCapacityUnits: N,
          WriteCapacityUnits: N
        }
      }

查询数据

const result = await this.dynamoClient.query({
  TableName: "my table",
  IndexName: "createdAt",
  KeyConditionExpression: "#status = :status and #createdAt > :createdAt",
  Limit: 5,
  ExpressionAttributeValues: {
    ":status": {
      "S": "active"
    },
    ":createdAt": {
      "S": "2020-12-10T15:00:00.000Z"
    }
  },
  ExpressionAttributeNames: {
    "#status": "status",
    "#createdAt": "createdAt"
  },
});