在 DynamoDB 中是否可以通过查询或扫描来获得 ORDER 结果?

是否可以在 DynamoDB 中使用查询或扫描 API 来订购结果?

我需要知道 DynamoDB 是否有类似于来自 SQL 查询的 ORDER BY 'field'

Thanks.

159720 次浏览

然而,对于许多现实世界的用例来说,排序显然是必需的,并且可以通过 散列和范围类型主键相应地进行建模:

在这种情况下,主键由两个属性组成 属性是 hash 属性,第二个属性是 range AmazonDynamoDB 在散列上构建无序的散列索引 主键属性和范围主键上的 < strong > 排序范围索引 键属性 . [强调我的]

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

更新: 您可以使用同样的方法按 局部次级指数局部次级指数属性排序。

You can use the sort-key and apply the ScanIndexForward parameter in a query to sort in either ascending or descending order. Here I limit items returned to 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));
}
});

If you are using Boto2 and you have the sort key on one of the columns in your table, you can sort what you retrieve in order or in reverse order by saying:

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 将按排序键值的相反顺序读取结果,然后将结果返回给客户端。

使用 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());
}
}

解决这个问题的另一个选择是

  1. 定义一个具有“普通”哈希键的本地辅助索引作为 LSI 的哈希键
  2. 将要排序的字段定义为 LSI 的“排序键”
  3. 查询 LSI 并根据需要设置顺序(见上文)

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

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

我从未想过这样一个琐碎的任务会在 DynamoDB 中变成一个问题。Dynamo 需要一些基本的分区。我设法通过添加额外的一列 地位来订购数据,然后使用这两个字段创建 GSI 索引。我通过 createdAt 字段使用 status = “ active”订购数据。

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