빅쿼리(Big Query) 연동하는 방법을 소개하겠습니다.

 

Spring-boot의 Maven을 사용하였고,

 

인증방법은 Credentials로 사용자 인증 정보가 담긴 json파일로 하였습니다.

 

pom.xml에 다음과 같이 추가합니다.

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>26.0.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-bigquery</artifactId>
  </dependency>
</dependencies>

 

프로젝트 resources 내에 사용자 인증 정보의 json파일을 업로드합니다.

resources/keys/credentials.json

 

BigQuery를 생성합니다.

package com.study.common.api.google.biquery;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.bigquery.*;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileInputStream;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 구글 빅쿼리
 */
public class ApiBigQueryAuthentication {

    /**
     * 구글 credentials.json을 통한 Biquery 생성
     * @return {BigQuery}
     */
    public static BigQuery getBigQuery() {
        try {
            // credentials.json 파일을 읽는다.
            File credentialsFile = ResourceUtils.getFile("classpath:keys/credentials.json");
            GoogleCredentials credentials;
            try (FileInputStream fileInputStream = new FileInputStream(credentialsFile)) {
                credentials = ServiceAccountCredentials.fromStream(fileInputStream);
            }
            
            // BigQuery 생성
            BigQuery bigQuery = BigQueryOptions.newBuilder()
            	.setCredentials(credentials)
                // credentials.json에 있는 project_id
                .setProjectId("project_id")
            	.build()
                .getService()
            ;
            return bigQuery;
        } catch (Exception e) {
            return null;
        }
    }
}

 

TableResult를 반환하는 메서드를 생성합니다.

/**
 * BigQuery 수행 및 결과
 * @param {String} query
 * @throws {Exception}
 * @return {TableResult}
 */
 public static TableResult bigQueryExecute(String query) throws Exception {
     BigQuery bigQuery = getBigQuery();
     
     QueryJobConfiguration queryJobConfiguration = 
         // Query
         QueryJobConfiguration.newBuilder(query)
             // 표준 SQL 사용
             // See: https://cloud.google.com/bigquery/sql-reference/
             setUseLegacySql(false)
         .build();
     
     // 보안문제로 JobId 생성
     JobId jobId = JobId.of(UUID.randomUUID().toString());
     Job job = bigQuery.create(JobInfo.newBuilder(queryJobConfiguration).setJobId(jobId).build());
     
     // 쿼리가 완성될 동안 대기
     job = job.waitFor();
     
     // 예외처리
     if (job == null) {
         throw new RuntimeException("쿼리가 존재하지 않습니다.");
     } else {
         if (job.getStatus().getError() != null) {
             String errorMessage =
                 job.getStatus().getError().getMessage() + "\n"
               + job.getStatus().getError().getReason() + "\n"
               + job.getStatus().getError().toString()
             ;
             throw new RuntimeException(errorMessage);
         } else {
             TableResult tableResult = job.getQueryResults();
             return tableResult;
         }
     }
 }

 

bigQueryExecute를 이용하여 TableResult를 받은 후 List<Map<String, Object>>에 넣어보겠습니다.

/**
 * 빅쿼리 조회
 * @return {List<Map<String, Object>>}
 * @throws {Exception}
 */
public List<Map<String, Object>> selectBigQuery() throws Exception {
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer.append("SELECT 'green' AS color     ");
    stringBuffer.append("    ,  '초록'  AS colorNm   ");
    stringBuffer.append("  FROM DUAL                 ");
    stringBuffer.append(" UNION ALL                  ");
    stringBuffer.append("SELECT 'pink'  AS color     ");
    stringBuffer.append("    ,  '분홍'  AS colorNm   ");
    stringBuffer.append("  FROM DUAL                 ");
    
    TableResult tableResult = bigQueryExecute(stringBuffer.toString());
    // TableResult를 담을 List 생성
    List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
    // List에 add할 map 선언
    Map<String, Object> map;
    
    int idx = 1;
    // tableResult for start
    for (FieldValueList fieldValueList:tableResult.iterateAll()) {
        // map 초기화
        map = new HashMap<String, Object>();
    
        // idx 초기화
        idx = 1;
        // FieldValueList for start
        for (FieldValue fieldValue:FieldValueList) {
            // Column의 Alias명은 알 수 없음.
            // 내가 선언한 쿼리의 순서를 인지하고 Map의 key를 알맞게 넣어줘야 함.
            if (idx == 1) map.put("color", fieldValue.getStringValue());
            
            if (idx == 2) map.put("colorNm", fieldValue.getStringValue());
            
            idx++;
        } // FieldValueList for end
        
        // list add
        dataList.add(map);
        
    } // tableResult for end
    return dataList;
}

 

 

 

Sencha에서 만든 Ext JS를 기반으로 만들어보려고 합니다.

 

버전은 6.2 기준으로 작성하겠습니다.

 

- 임시 중단

 

Ext.define('App.views.com.notice.Notice')

 

Mysql의 경우 RECURSIVE를 이용하여 특정기간의 일(목록)을 구할 수 있다.

 

예를들면 2022-01-10 ~ 2022-01-15의 목록의 결과는 다음과 같다.

2022-01-10, 2022-01-11, 2022-01-12, 2022-01-13, 2022-01-14, 2022-01-15

 

WITH RECURSIVE VIEW_DATE AS (
    SELECT STR_TO_DATE('20220110', '%Y%m%d') AS TODAY
     UNION ALL
    SELECT DATE_ADD(VIEW_DATE.TODAY, INTERVAL 1 DAY) 
      FROM VIEW_DATE 
     WHERE DATE_ADD(VIEW_DATE.TODAY, INTERVAL 1 DAY) <= '20220115'
)
SELECT TODAY
  FROM VIEW_DATE;

 

DB 조회 결과

 

쿼리를 수행하는 도중 서브쿼리(Subquery)가 존재할 때

 

단 1개의 컬럼만 도출되어야 하나, 2개 이상의 컬럼이 도출 되었을 때 발생하는 에러이다.

 

쿼리를 다시 확인하고, 서브쿼리(Subquery)를 올바르게 사용하자.

+ Recent posts