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.