DynamoDB에서 쿼리 또는 스캔을 사용하여 결과를 주문할 수 있습니까?


86

DynamoDB에서 Query 또는 Scan API를 사용하여 결과를 주문할 수 있습니까?

DynamoDB에 SQL 쿼리의 [ORDER BY 'field']와 같은 것이 있는지 알고 싶습니다.

감사.

답변:


44

그러나 명시 적으로는 아니지만 많은 실제 사용 사례에서 순서가 분명히 필요하며 그에 따라 해시 및 범위 유형 기본 키 를 사용하여 모델링 할 수 있습니다 .

이 경우 기본 키는 두 가지 속성으로 구성됩니다. 첫 번째 속성은 해시 속성이고 두 번째 속성은 범위 속성입니다. Amazon DynamoDB는 해시 기본 키 속성에 정렬되지 않은 해시 인덱스를 만들고 범위 기본 키 속성에 정렬 된 범위 인덱스를 만듭니다. [내 강조]

그런 다음을 통해 선택적으로 요청 항목이 범위 인덱스를 사용할 수 있습니다 RangeKeyCondition의 의 매개 변수 쿼리 API 및 지정 앞이나 인덱스의 뒤로 통과 비아 (즉, 정렬 방향) ScanIndexForward 매개 변수입니다.

업데이트 : 동일한 방식으로 local secondary index 가있는 속성별로 주문할 수 있습니다 .


19
ScanIndexForward 매개 변수는 Scan이 아닌 Query 에만 적용되는 것 같습니다 . 쿼리를 사용하여 테이블에있는 모든 항목의 순서가 매겨진 목록을 어떻게 반환합니까? 스캔은 "*"를 반환하는 방법 인 것 같지만 결과 주문에 대한 매개 변수가없는 것 같습니다.
— case2000

이 기능을 사용하지 않았고 그것에 대해 읽었을 뿐이지 만 Query는 수신 된 결과의 수를 제한 하기 위해 Limit 지정을 지원하며 , 제한에 도달했을 때 쿼리와 일치하는 항목이 더 있으면 LastEvaluatedKey를 받게됩니다. 다른 쿼리를 수행하고 결과를 계속 검색하는 데 사용할 수 있습니다.
— fernio

1
중요한 문제 : 반환 된 결과는 실제로 정렬되지 않습니다. 정렬은 '제한'값을 적용하거나 항목 수가 1MB 조회 제한을 초과하는 경우에만 작동합니다. 예를 들어 파티션 키 'p1'과 정렬 키 ([ 'b', 'd', 'a', 'c', 'e'])가있는 5 개의 레코드가있을 수 있습니다. 'p1'만 쿼리하면 [ 'b', 'd', 'a', 'c', 'e']를 받게됩니다. 그러나 Limit를 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

키가 아닌 필드를 기반으로 반환하려면 어떻게해야합니까? created_on 번호 필드와 같은
— 유 서프

그런 다음 모든 레코드를 가져온 다음 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

2

문제를 해결해야하는 또 다른 옵션은

  1. LSI의 해시 키가 될 "일반"해시 키를 사용하여 local secondary index를 정의합니다.
  2. LSI의 "정렬 키"로 정렬하려는 필드를 정의하십시오.
  3. LSI를 쿼리하고 원하는대로 순서를 설정합니다 (위 참조).

이렇게하면 필요에 따라 테이블 값을 정렬 할 수 있습니다. 전체 쿼리를 가져온 다음 나중에 필터링 할 필요없이 테이블에서 가장 높은 순위의 항목을 찾는 매우 효율적인 방법입니다.


위는 무엇입니까? 일반 해시가 정렬 생성 ID에 대해 정렬되지 않은 경우 포함하는 것이 작동하지 않는 것 같습니다. 내가 뭔가를 놓치고 있습니까?
— Samantha Atkins

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는 사실, DynamoDB의 그들이 (정렬 키 값에 의해) 저장되는 순서대로 결과를 반환합니다. 이것이 기본 동작입니다. ScanIndexForward가 false이면 DynamoDB는 정렬 키 값에 따라 역순으로 결과를 읽은 다음 결과를 클라이언트에 반환합니다.


0

테이블이 이미 존재하는 경우 테이블에 대해 원하는 속성에 GSI (Global Secondary Index)를 추가하고 Scan이 아닌 Query를 사용합니다. 테이블을 생성하려는 경우 원하는 속성에 LSI (Local Secondary Index)를 추가 할 수 있습니다.


0

그런 사소한 작업이 DynamoDB에서 문제가 될 수 있다고는 생각하지 못했습니다. Dynamo에는 몇 가지 기본 파티션이 필요합니다. 추가 열 상태를 추가하여 데이터를 주문했습니다. 다음 두 필드를 사용하여 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"
  },
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.