Amazon dynamodb 是否可以在DynamoDB中通过查询或扫描对结果进行排序?

Amazon dynamodb 是否可以在DynamoDB中通过查询或扫描对结果进行排序?,amazon-dynamodb,Amazon Dynamodb,是否可以在DynamoDB中使用查询或扫描API对结果进行排序 我需要知道DynamoDB是否有类似于SQL查询中按“字段”排序的 谢谢。不过,对于许多真实世界的用例来说,排序显然是必需的,并且可以通过相应的方式进行建模: 在这种情况下,主键由两个属性组成。第一 属性是散列属性,第二个是范围 属性AmazonDynamodb在散列上构建一个无序散列索引 主键属性和主范围上的排序范围索引 键属性。[我的重点] 然后,您可以使用此范围索引通过的RangeKeyCondition参数选择性地请求项目,

是否可以在DynamoDB中使用查询或扫描API对结果进行排序

我需要知道DynamoDB是否有类似于SQL查询中按“字段”排序的


谢谢。

不过,对于许多真实世界的用例来说,排序显然是必需的,并且可以通过相应的方式进行建模:

在这种情况下,主键由两个属性组成。第一 属性是散列属性,第二个是范围 属性AmazonDynamodb在散列上构建一个无序散列索引 主键属性和主范围上的排序范围索引 键属性。[我的重点]

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


更新:您可以按具有的属性按相同方式排序。

您可以使用排序键并在a中应用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));
    }
});

如果您使用的是boto2,并且表中的一列上有排序键,则可以按顺序或相反顺序对检索的内容进行排序,方法是:

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

如果您使用的是boto3,并且您希望对结果进行排序的列上有排序键,您可以对检索到的数据进行排序,方法是:

result = users.query_2(
    account_type__eq='standard_user',
    reverse=True)
result = users.query(
    KeyConditionExpression=Key('account_type').eq('standard_user'),
    ScanIndexForward=True)
请记住,在boto3中,如果ScanIndexForward为true,DynamoDB将按存储顺序(按排序键值)返回结果。这是默认行为。如果ScanIndexForward为false,DynamoDB将按排序键值的相反顺序读取结果,然后将结果返回给客户端。

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

请在下面查找用于查找单个记录的查询页面的代码

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());
    }
}
public void fetchLatestEvents(){
EventLogEntitySave实体=新建EventLogEntitySave();
entity.setId(“1C6RR7JM0JS100037_contentManagementActionComplete”);
DynamoDBQueryExpression queryExpression=新的DynamoDBQueryExpression(),带有HashKeyValues(实体);
queryExpression.setScanIndexForward(false);
queryExpression.withLimit(1);
queryExpression.setLimit(1);
List result=dynamoDBMapper.queryPage(EventLogEntitySave.class,queryExpression).getResults();
System.out.println(“记录大小=“+result.size());
}
@发电机表(tableName=“生产测试”)
公共类EventLogEntitySave{
@发电机钥匙
私有字符串id;
私有字符串对账过程ID;
私有字符串vin;
私有字符串源;
}
公共类DynamoDBConfig{
@豆子
公共AmazonDynamoDB AmazonDynamoDB(){
字符串accesskey=“”;
字符串secretkey=“”;
//
//创建dynamo客户端
BasicAWSCredentials credentials=新的BasicAWSCredentials(accesskey、secretkey);
AmazonDynamoDB dynamo=新的AmazonDynamoDBClient(凭证);
dynamo.setRegion(Region.getRegion(Regions.US_WEST_2));
回程发电机;
}
@豆子
公共DynamoDBMapper DynamoDBMapper(){
返回新的DynamoDBMapper(amazonDynamoDB());
}
}

解决此问题的另一个方法是

  • 定义一个本地二级索引,该索引的“普通”散列键也是LSI的散列键
  • 将要排序的字段定义为LSI的“排序键”
  • 查询LSI并根据需要设置顺序(见上文)

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

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

    我从未想过,这样一项琐碎的任务会在DynamoDB中变成问题。发电机需要一些基本的分区。我通过添加一个额外的列状态来对数据进行排序,然后使用这两个字段创建GSI索引。我通过createdAt字段订购状态为“活动”的数据

    创建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"
      },
    });
    

    ScanIndexForward参数似乎仅适用于,不正确?如何使用查询返回表中所有项的有序分页列表?扫描似乎是返回“*”的方式,但它似乎没有用于排序结果的参数。我没有使用此功能,只是了解了它,但查询支持指定一个,以限制收到的结果的数量,如果达到限制时有更多项与您的查询相匹配,您将收到一个LastEvaluatedKey,可用于执行另一个查询并继续检索结果。重要提示:返回的结果实际上不会被排序。只有在应用“限制”值或项目数超过1MB查找限制时,排序才会起作用。例如,您可能有5条记录,分区键为'p1',排序键为:['b','d','a','c','E']。如果只对“p1”执行查询,您将收到['b','d','a','c','e']。但如果您指定限制为2,它将返回['b','a'],问题是您是否要返回所有项目。从本质上说,这意味着您必须创建一个新的伪列,将其中的相同值分配给所有行,在该列上创建一个GSI,并调用查询而不是扫描。如果我想基于某个非键字段返回,该怎么办?就像在数字字段上创建_一样,您可能希望获取所有记录,然后使用javascript或类似的方法过滤这些记录。DynamoDB基本上是一个功能有限的键值存储。但是速度非常快