AWS

[AWS] DynamoDB - query 및 scan 코드 작성 (with Node.js)

itaeiou 2022. 2. 15. 17:15
반응형

AWS DynamoDB

저번 포스트에서는 Node.js 서버에서 DynamoDB를 활용한 CRUD 코드 작성에 대해 작성했는데

Read 부분인 query와 scan 양이 많아 별도로 다루려합니다.

아래 링크의 공식 도큐먼트를 참고했으나, 세부 코드는 조금씩 다를 수 있습니다.

https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.04.html

 

4단계: AWS SDK for JavaScript를 사용하여 DynamoDB에서 데이터 쿼리 및 스캔 - Amazon DynamoDB

ExpressionAttributeNames는 이름을 교체합니다. year가 Amazon DynamoDB의 예약어이기 때문에 사용합니다. 이를 KeyConditionExpression을 포함한 어떤 표현식에서도 직접 사용할 수 없습니다. 표현식 속성 이름인

docs.aws.amazon.com

 

query와 scan 차이

DynamoDB의 데이터를 읽어오는 메서드는 query와 scan 두가지가 있습니다.

  • query
    • 파티션 키와 정렬 키로 값을 읽어오는 방식
    • sacn과 비교했을 때 속도가 빠름
  • scan
    • 전체 데이터를 모두 읽어오는 방식
    • query 보다 속도가 느림

 

 

예제 테이블

앞의 포스트에서 사용한 알림 정보 테이블을 그대로 사용하겠습니다.

 

테이블 명 : NOTIFICATION

파티션 키 : user_id

정렬 키 : uuid

로컬인덱스1 : create_datetime-index (파티션: user_id, 정렬: create_dataetime, 프로젝션: ALL)

로컬인덱스2 : read_yn-index (파티션: user_id, 정렬: read_yn, 프로젝션: ALL)

 

https://jane-aeiou.tistory.com/63

 

[AWS] DynamoDB - 테이블 생성하기

AWS DynamoDB AWS DynamoDB는 AWS에서 제공하는 서버리스 NoSQL입니다. Key-Value 데이터베이스로 스키마가 복잡하지 않다는 것이 장점입니다. 비용은 사용한 만큼만 내면 되기 때문에 많은 비용이 들지 않

jane-aeiou.tistory.com

 

config 설정

docClient를 설정합니다. (CRUD 포스트의 config 설정과 동일)

앞선 포스트를 따라오신 분들은 그대로 사용하시면 됩니다.

const AWS = require('aws-sdk');

const docClient = new AWS.DynamoDB.DocumentClient({
    accessKeyId: "myAccessKeyId",
    secretAccessKey: "mySecretAccessKey",
    region: 'ap-northeast-2',
    endpoint: "http://dynamodb.ap-northeast-2.amazonaws.com"
});

 

query - 기본

기본적인 query 사용법은 다음과 같습니다.

TableName과 파티션키는 필수로 사용해야 합니다.

KeyConditionExpression에 조건문을 입력하고

ExpressionAttributeValues에서 변수 값을 입력합니다.

query의 조건으로는 파티션 키와 정렬 키만 사용할 수 있습니다.

// 유저의 알림 리스트 조회
var params = {
    TableName: "NOTIFICATION",
    KeyConditionExpression: "user_id = :user_id",
    ExpressionAttributeValues: {
        ":user_id": user_id
    }
}

docClient.query(params).promise()
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
    });

 

query - 조건 추가

다음 예시는 유저가 읽지 않은 알림 리스트롤 조회하는 코드입니다.

예시 테이블에서는 user_id/uuid가 키로 지정되어있지만, 우리가 사용해야하는 것은 user_id/read_yn이기 때문에 로컬 인덱스로 생성해둔 read_yn-index 를 사용합니다.(글로벌 인덱스도 코드는 동일하게 작성합니다.)

조건이 여러개일 땐 and/or 로 연결합니다.

 

// 유저가 읽지 않은 알림 리스트 조회
var params = {
    TableName: "NOTIFICATION",
    IndexName: "read_yn-index",
    KeyConditionExpression: "user_id = :user_id and read_yn = :read_yn",
    ExpressionAttributeValues: {
        ":user_id": user_id,
        ":read_yn": "N"
    }
}

docClient.query(params).promise()
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
    });

 

query - 정렬

기본 예제에서 시간순 정렬을 추가해보겠습니다.

ScanIndexForward 은 정렬키로 리스트를 정렬해주는 옵션입니다.

ture이면 오름차순, false이면 내림차순으로 정렬합니다.

기존 정렬키 uuid가 아닌 datetime으로 정렬을 해야하기 때문에 마찬가지로 인덱스를 사용합니다.

// 알림 리스트를 최신순으로 정렬
var params = {
    TableName: "NOTIFICATION",
    IndexName: "create_datetime_index",
    KeyConditionExpression: "user_id = :user_id",
    ExpressionAttributeValues: {
        ":user_id": user_id
    },
    ScanIndexForward: false
}

docClient.query(params).promise()
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
    });

 

scan

scan은 파티션키/정렬키가 아니여도 조건으로 사용할 수 있습니다.

query는와 다르게 테이블의 모든 항목을 확인하고, 필터를 적용하기 때문에 속도가 느리다는 단점이 있습니다.

KeyConditionExpression 가 아닌 FilterExpression 를 사용합니다.

조건과 변수를 작성하는 방식은 query와 동일하며, scan 매서드를 사용합니다.

var params = {
    TableName: "NOTIFICATION",
    FilterExpression: "user_id = :user_id and category = :category",
    ExpressionAttributeValues: {
        ":user_id": user_id,
        ":category": category
    }
}

docClient.scan(params).promise()
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
    });
반응형