DynamoDB排序并选择前20条记录

时间:2017-11-15 11:06:04

标签: java amazon-dynamodb

我希望在应用一些过滤器后,根据存储为ISO-8601格式uuuu-MM-dd的日期字段对前10或20等基本上可配置的数字进行排序。

@DynamoDBTable(tableName = "Data")
@NoArgsConstructor
@ToString
public class Data {

    private LocalDate date;
    @Setter
    private Long number;
    @Setter
    private STATUS status;

    @DynamoDBHashKey
    @DynamoDBTypeConverted(converter = LocalDateConverter.class)
    public LocalDate getDate() {
        return date;
    }

    @DynamoDBTypeConverted(converter = LocalDateConverter.class)
    public void setDate(LocalDate date) {
        this.date = date;
    }

    @DynamoDBIndexHashKey(globalSecondaryIndexName = "idx_Data_number")
    public Long getCompetitionId() {
        return number;
    }

    @DynamoDBTypeConvertedEnum
    @DynamoDBIndexHashKey(globalSecondaryIndexName = "idx_Data_status")
    public STATUS getStatus() {
        return status;
    }
}

我需要根据数字和多个状态过滤后根据日期字段排序的20条记录。我使用ScanRequest基本上过滤了记录。现在我想限制结果并根据日期获得最佳记录。

@AllArgsConstructor
public class DataRepositoryImpl implements DataRepository {
 private final DynamoDBMapper dynamoDBMapper;
 private final AmazonDynamoDB amazonDynamoDB;

 @Override
 public List<Data> findAll(Long number, List<String> status) {
    Condition numberCondition = new Condition()
            .withComparisonOperator(ComparisonOperator.EQ)
            .withAttributeValueList(new AttributeValue().withN(String.valueOf(number)));

    List<AttributeValue> attributeValues = newArrayList();
    status.forEach(s -> attributeValues.add(new AttributeValue().withS(s)));
    Condition statusCondition = new Condition()
            .withComparisonOperator(ComparisonOperator.IN)
            .withAttributeValueList(attributeValues);

    Map<String, Condition> conditions = newHashMap();
    conditions.put("number", numberCondition);
    conditions.put("status", statusCondition);

    ScanRequest scanRequest = new ScanRequest()
            .withTableName("Data")
            .withScanFilter(conditions)
            .withConditionalOperator(ConditionalOperator.AND);

    ScanResult scanResult = amazonDynamoDB.scan(scanRequest);
    return dynamoDBMapper.marshallIntoObjects(Data.class, scanResult.getItems());
    }
}

3 个答案:

答案 0 :(得分:2)

DynamoDB仅按 SORT KEY 属性对数据进行排序。

DynamoDB没有按照sort key除外的任何属性(即任何非键属性或分区键属性)对数据进行排序的功能。

  

分区键和排序键 - 称为复合主键,   这种类型的密钥由两个属性组成。第一个属性是   分区键,第二个属性是排序键。 DynamoDB   使用分区键值作为内部哈希函数的输入。   散列函数的输出确定分区(物理   存储项目的DynamoDB内部存储。所有   具有相同分区键的项目按排序顺序存储在一起   按排序键值。

DynamoDB将数据存储在多个分区中。与RDBMS一样,它也没有任何ORDER BY子句。但是,它具有ScanIndexForward选项,只能应用于Sort键属性。

  

ScanIndexForward - (布尔值)指定索引遍历的顺序:   如果为true(默认),则以递增顺序执行遍历;如果   false,遍历按降序执行。

答案 1 :(得分:1)

我不相信您可以使用DynamoDB实现这一目标。您必须使用应用程序代码订购和过滤结果。

如果您使用排序键,DynamoDB返回有序结果的唯一方法。但是,您的初始查询是多维的(一个数字,多个状态&#39;),因此您无法创建在这种情况下可用的分区。

如果您想查询单个号码,并按日期排序,则可以使用数字作为分区键,使用新的日期作为长号码&#39;属性作为排序键。 DynamoDB密钥只能是String,Number or Binary attributes。我假设您的LocalDateConverter将日期更改为字符串,因此这不会成为一个好的排序键。但是,您可以添加一个新的属性,该属性是一个数字,并以YYYYMMDDHHMMSS格式表示日期,这自然会按正确的顺序排序。然后,您可以使用DynamoDB ScanIndexForward函数并将结果集限制为给定数量的项目。

答案 2 :(得分:0)

您可以在扫描中设置LimitScanRequest#setLimit

  

要评估的最大项目数(不一定是   匹配项目)。如果DynamoDB处理的项目数量最多   在处理结果时限制,它会停止操作并返回   截至该点的匹配值,以及LastEvaluatedKey中的键   适用于后续操作,以便您可以在哪里接听   离开了。

但我怀疑dynamodb会对scan中的任何键进行排序。

您可以创建本地索引,这将帮助您检索限制和排序。