Redash API로 동적으로 결과 얻기

11563 단어 redash

전제


  • Redash 2.0.0+b2990

  • 기사 중의 기법


  • <host>는 Redash의 호스트를 의미합니다. 예를 들어, 환경의 Redash GUI에 액세스 할 때 https://www.example.com/redash/에 액세스하는 경우 호스트입니다. <host>/api 라고 기재하면https://www.example.com/redash/api 를 의미합니다.
  • 그 외, <>로 둘러싼 문자는 적절히 변수를 의미합니다. <query_id>

  • 사용자 API 키 가져오기



    메뉴 > 사용자 이름 > API Key


    쿼리 실행



    다음 URI를 POST하면 쿼리를 실행할 수 있습니다.
    <host>/api/queries/<query_id>/refresh?api_key=<user_api_key>
    

    쿼리 중에 매개변수가 있는 경우



    쿼리의 매개 변수는 p_<parameter_name>=<value> 형식으로 URL 쿼리 매개 변수로 전달됩니다.
    예를 들어
    select
      *
    from
      users
    where
      user_id = {{user_id}}
    

    라는 쿼리를 user_id=12345에서 실행하는 경우 POST할 URI는 다음과 같습니다.
    <host>/api/queries/<query_id>/refresh?p_user_id=12345&api_key=<user_api_key>
    

    응답



    다음과 같은 JSON이 반환됩니다.
    {
      "job": {
        "status": 2,
        "error": "",
        "id": "XXXXXXXXXXX",
        "query_result_id": null,
        "updated_at": 0
      }
    }
    

    ※이후, 상기의 JSON의 job.id 의 값을 <job_id> 로서 취급합니다.

    작업 상태 얻기



    다음 URI를 GET하면 작업 상태를 얻을 수 있습니다.
    <host>/api/jobs/<job_id>?api_key=<user_api_key>
    

    응답은 /api/queries/<query_id>/refresh와 같은 형식입니다.
    작업이 종료되면 query_result_id 값이 설정됩니다.query_result_id 값이 null이면 작업이 끝날 때까지 기다려야 합니다.

    작업 결과 얻기



    다음 URI를 GET하면 작업 결과를 얻을 수 있습니다.
    <host>/api/queries/<query_id>/results/<query_result_id>.json?api_key=<user_api_key>
    

    파일 확장자는 .json 외에 .csv가 있습니다.

    스니펫(GAS용)



    …를 근거로 한 코드를 GAS용으로 쓰면 이렇게 됩니다.
    /**
     * 
     * @param {String} host https://redash.example.com 的なもの。末尾にスラッシュはつけないでください。
     * @param {String} queryId 123等
     * @param {String} apiKey 
     * @param {any[]} param クエリのパラメータの連想配列
     */
    function callRedash(host, queryId, apiKey, param) {
        let queryParams = [`api_key=${apiKey}`]
        if (param) {
            for (let key in param) {
                const queryParam = `p_${key}=${param[key]}`;
                queryParams.push(queryParam);
            }
        }
        const refreshUri = `${host}/api/queries/${queryId}/refresh?${queryParams.join('&')}`;
        const refreshResult = UrlFetchApp.fetch(refreshUri, { "method": "POST" });
        const jobId = JSON.parse(refreshResult).job.id;
    
        const jobStatusUri = `${host}/api/jobs/${jobId}?api_key=${apiKey}`;
        let queryResultId = null;
        const startMills = new Date().getTime();
        while (true) {
            const endMills = new Date().getTime();
            if (endMills - startMills > (4 * 60 * 1000)) {
                // GASの実行時間上限は5分なので、4分経過した時点で中断します。
                throw new Error("Redashへの問い合わせ開始から4分以上経過したため、中断します。");
            }
            const jobStatus = JSON.parse(UrlFetchApp.fetch(jobStatusUri)).job;
            const status = jobStatus.status;
            if (status === 3 || status === 4) {
                queryResultId = jobStatus.query_result_id;
                break; // 結果を取得できたのでbreak
            }
            Utilities.sleep(5000); //  5秒待機
        }
    
        const jobResultUri = `${host}/api/queries/${queryId}/results/${queryResultId}.json?api_key=${apiKey}`;
        const result = JSON.parse(UrlFetchApp.fetch(jobResultUri));
        return result.query_result.data.rows;
    }
    

    좋은 웹페이지 즐겨찾기