JSON 쿼리

JSON 쿼리 (JSON querying) API

Apache Druid에 JSON 기반 네이티브 쿼리를 제출하는 API 엔드포인트를 다룹니다. 쿼리 제출 방법과 쿼리별 서버 위치 조회 방법을 설명해요.

출처: 문서

본문

이 문서는 Apache Druid에 JSON 기반 네이티브 쿼리(native query)를 제출하는 API 엔드포인트를 설명합니다.

이 문서에서 http://SERVICE_IP:SERVICE_PORT는 배포의 서버 주소와 서비스 포트를 위한 자리표시자입니다. 예를 들어 quickstart 구성에서 http://ROUTER_IP:ROUTER_PORT를 http://localhost:8888로 교체하세요.

쿼리 제출

JSON 기반 네이티브 쿼리를 제출합니다. 요청 본문이 바로 네이티브 쿼리입니다.

Druid는 다양한 유스케이스를 위해 여러 타입의 쿼리를 지원합니다. 모든 쿼리는 다음 속성을 요구합니다.

  • queryType: 쿼리 타입을 나타내는 문자열. Druid는 다음 네이티브 쿼리 타입을 지원합니다: timeseries, topN, groupBy, timeBoundaries, segmentMetadata, datasourceMetadata, scan, search.
  • dataSource: 쿼리할 데이터의 소스를 정의하는 문자열 또는 객체. 가장 흔한 값은 쿼리할 데이터소스의 이름입니다. 자세한 내용은 Datasources를 참고하세요.

쿼리 타입이나 유스케이스에 따른 추가 속성은 available native queries를 참고하세요.

URL

POST /druid/v2

쿼리 파라미터

  • pretty (선택) — Druid가 들여쓰기와 줄바꿈을 사용해 응답을 pretty-printed 형식으로 반환합니다.

응답

  • 200 SUCCESS — 쿼리를 성공적으로 제출함
  • 400 BAD REQUEST — 잘못된 쿼리로 인한 오류. 다음 형식의 오류를 자세히 설명하는 JSON 객체를 반환합니다.
{
    "error": "A well-defined error code.",
    "errorMessage": "A message with additional details about the error.",
    "errorClass": "Class of exception that caused this error.",
    "host": "The host on which the error occurred."
}

가능한 오류 메시지에 대한 자세한 내용은 query execution failures를 참고하세요.

예제 쿼리: topN

다음 예시는 topN 쿼리를 보여줍니다. 이 쿼리는 social_media 데이터소스를 분석해 views 메트릭에서 가장 많은 뷰 수를 가진 username 차원의 상위 5명의 사용자를 반환합니다.

cURL

curl "http://ROUTER_IP:ROUTER_PORT/druid/v2?pretty=null" \
--header 'Content-Type: application/json' \
--data '{
  "queryType": "topN",
  "dataSource": "social_media",
  "dimension": "username",
  "threshold": 5,
  "metric": "views",
  "granularity": "all",
  "aggregations": [
    {
      "type": "longSum",
      "name": "views",
      "fieldName": "views"
    }
  ],
  "intervals": [
    "2022-01-01T00:00:00.000/2024-01-01T00:00:00.000"
  ]
}'

HTTP

POST /druid/v2?pretty=null HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
Content-Type: application/json
Content-Length: 336

{
  "queryType": "topN",
  "dataSource": "social_media",
  "dimension": "username",
  "threshold": 5,
  "metric": "views",
  "granularity": "all",
  "aggregations": [
    {
      "type": "longSum",
      "name": "views",
      "fieldName": "views"
    }
  ],
  "intervals": [
    "2022-01-01T00:00:00.000/2024-01-01T00:00:00.000"
  ]
}

예제 응답: topN

[
  {
      "timestamp": "2023-07-03T18:49:54.848Z",
      "result": [
          {
              "views": 11591218026,
              "username": "gus"
          },
          {
              "views": 11578638578,
              "username": "miette"
          },
          {
              "views": 11561618880,
              "username": "leon"
          },
          {
              "views": 11552609824,
              "username": "mia"
          },
          {
              "views": 11551537517,
              "username": "milton"
          }
      ]
  }
]

예제 쿼리: groupBy

다음 예시는 social_media 데이터소스에서 게시물 대비 투표 비율이 가장 높은 사용자를 가져오기 위해 groupBy 타입의 JSON 쿼리를 제출합니다.

이 쿼리에서:

  • upvoteSum 집계는 각 사용자의 투표 합계를 계산합니다.
  • postCount 집계는 각 사용자의 게시물 합계를 계산합니다.
  • upvoteToPostRatio는 upvoteSum과 postCount를 나눠 비율을 계산하는 post-aggregation입니다.
  • 결과는 upvoteToPostRatio를 기준으로 내림차순 정렬됩니다.

cURL

curl "http://ROUTER_IP:ROUTER_PORT/druid/v2" \
--header 'Content-Type: application/json' \
--data '{
  "queryType": "groupBy",
  "dataSource": "social_media",
  "dimensions": ["username"],
  "granularity": "all",
  "aggregations": [
    { "type": "doubleSum", "name": "upvoteSum", "fieldName": "upvotes" },
    { "type": "count", "name": "postCount", "fieldName": "post_title" }
  ],
  "postAggregations": [
    {
      "type": "arithmetic",
      "name": "upvoteToPostRatio",
      "fn": "/",
      "fields": [
        { "type": "fieldAccess", "name": "upvoteSum", "fieldName": "upvoteSum" },
        { "type": "fieldAccess", "name": "postCount", "fieldName": "postCount" }
      ]
    }
  ],
  "intervals": ["2022-01-01T00:00:00.000/2024-01-01T00:00:00.000"],
  "limitSpec": {
    "type": "default",
    "limit": 1,
    "columns": [
      { "dimension": "upvoteToPostRatio", "direction": "descending" }
    ]
  }
}'

HTTP

POST /druid/v2?pretty=null HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
Content-Type: application/json
Content-Length: 817

{
  "queryType": "groupBy",
  "dataSource": "social_media",
  "dimensions": ["username"],
  "granularity": "all",
  "aggregations": [
    { "type": "doubleSum", "name": "upvoteSum", "fieldName": "upvotes" },
    { "type": "count", "name": "postCount", "fieldName": "post_title" }
  ],
  "postAggregations": [
    {
      "type": "arithmetic",
      "name": "upvoteToPostRatio",
      "fn": "/",
      "fields": [
        { "type": "fieldAccess", "name": "upvoteSum", "fieldName": "upvoteSum" },
        { "type": "fieldAccess", "name": "postCount", "fieldName": "postCount" }
      ]
    }
  ],
  "intervals": ["2022-01-01T00:00:00.000/2024-01-01T00:00:00.000"],
  "limitSpec": {
    "type": "default",
    "limit": 1,
    "columns": [
      { "dimension": "upvoteToPostRatio", "direction": "descending" }
    ]
  }
}

예제 응답: groupBy

[
    {
        "version": "v1",
        "timestamp": "2022-01-01T00:00:00.000Z",
        "event": {
            "upvoteSum": 8.0419541E7,
            "upvoteToPostRatio": 69.53014661762697,
            "postCount": 1156614,
            "username": "miette"
        }
    }
]

쿼리에 대한 세그먼트 정보 가져오기

요청 본문에 제공된 쿼리와 연관된 서버 위치를 포함해 세그먼트 정보가 담긴 객체를 가진 배열을 가져옵니다.

URL

POST /druid/v2/candidates

쿼리 파라미터

  • pretty (선택) — Druid가 들여쓰기와 줄바꿈을 사용해 응답을 pretty-printed 형식으로 반환합니다.

응답

  • 200 SUCCESS — 세그먼트 정보를 성공적으로 조회함
  • 400 BAD REQUEST — 잘못된 쿼리로 인한 오류. 다음 형식의 오류를 자세히 설명하는 JSON 객체를 반환합니다.
{
    "error": "A well-defined error code.",
    "errorMessage": "A message with additional details about the error.",
    "errorClass": "Class of exception that caused this error.",
    "host": "The host on which the error occurred."
}

가능한 오류 메시지에 대한 자세한 내용은 query execution failures를 참고하세요.

샘플 요청

cURL

curl "http://ROUTER_IP:ROUTER_PORT/druid/v2/candidates" \
--header 'Content-Type: application/json' \
--data '{
  "queryType": "topN",
  "dataSource": "social_media",
  "dimension": "username",
  "threshold": 5,
  "metric": "views",
  "granularity": "all",
  "aggregations": [
    {
      "type": "longSum",
      "name": "views",
      "fieldName": "views"
    }
  ],
  "intervals": [
    "2022-01-01T00:00:00.000/2024-01-01T00:00:00.000"
  ]
}'

HTTP

POST /druid/v2/candidates HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
Content-Type: application/json
Content-Length: 336

{
  "queryType": "topN",
  "dataSource": "social_media",
  "dimension": "username",
  "threshold": 5,
  "metric": "views",
  "granularity": "all",

  "aggregations": [
    {
      "type": "longSum",
      "name": "views",
      "fieldName": "views"
    }
  ],
  "intervals": [
    "2020-01-01T00:00:00.000/2024-01-01T00:00:00.000"
  ]
}

샘플 응답

[
  {
      "interval": "2023-07-03T18:00:00.000Z/2023-07-03T19:00:00.000Z",
      "version": "2023-07-03T18:51:18.905Z",
      "partitionNumber": 0,
      "size": 21563693,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-03T19:00:00.000Z/2023-07-03T20:00:00.000Z",
      "version": "2023-07-03T19:00:00.657Z",
      "partitionNumber": 0,
      "size": 6057236,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-05T21:00:00.000Z/2023-07-05T22:00:00.000Z",
      "version": "2023-07-05T21:09:58.102Z",
      "partitionNumber": 0,
      "size": 223926186,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-05T21:00:00.000Z/2023-07-05T22:00:00.000Z",
      "version": "2023-07-05T21:09:58.102Z",
      "partitionNumber": 1,
      "size": 20244827,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-05T22:00:00.000Z/2023-07-05T23:00:00.000Z",
      "version": "2023-07-05T22:00:00.524Z",
      "partitionNumber": 0,
      "size": 104628051,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-05T22:00:00.000Z/2023-07-05T23:00:00.000Z",
      "version": "2023-07-05T22:00:00.524Z",
      "partitionNumber": 1,
      "size": 1603995,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-05T23:00:00.000Z/2023-07-06T00:00:00.000Z",
      "version": "2023-07-05T23:21:55.242Z",
      "partitionNumber": 0,
      "size": 181506843,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T00:00:00.000Z/2023-07-06T01:00:00.000Z",
      "version": "2023-07-06T00:02:08.498Z",
      "partitionNumber": 0,
      "size": 9170974,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T00:00:00.000Z/2023-07-06T01:00:00.000Z",
      "version": "2023-07-06T00:02:08.498Z",
      "partitionNumber": 1,
      "size": 23969632,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T01:00:00.000Z/2023-07-06T02:00:00.000Z",
      "version": "2023-07-06T01:13:53.982Z",
      "partitionNumber": 0,
      "size": 599895,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T01:00:00.000Z/2023-07-06T02:00:00.000Z",
      "version": "2023-07-06T01:13:53.982Z",
      "partitionNumber": 1,
      "size": 1627041,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T02:00:00.000Z/2023-07-06T03:00:00.000Z",
      "version": "2023-07-06T02:55:50.701Z",
      "partitionNumber": 0,
      "size": 629753,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T02:00:00.000Z/2023-07-06T03:00:00.000Z",
      "version": "2023-07-06T02:55:50.701Z",
      "partitionNumber": 1,
      "size": 1342360,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T04:00:00.000Z/2023-07-06T05:00:00.000Z",
      "version": "2023-07-06T04:02:36.562Z",
      "partitionNumber": 0,
      "size": 2131434,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T05:00:00.000Z/2023-07-06T06:00:00.000Z",
      "version": "2023-07-06T05:23:27.856Z",
      "partitionNumber": 0,
      "size": 797161,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T05:00:00.000Z/2023-07-06T06:00:00.000Z",
      "version": "2023-07-06T05:23:27.856Z",
      "partitionNumber": 1,
      "size": 1176858,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T06:00:00.000Z/2023-07-06T07:00:00.000Z",
      "version": "2023-07-06T06:46:34.638Z",
      "partitionNumber": 0,
      "size": 2148760,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T07:00:00.000Z/2023-07-06T08:00:00.000Z",
      "version": "2023-07-06T07:38:28.050Z",
      "partitionNumber": 0,
      "size": 2040748,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T08:00:00.000Z/2023-07-06T09:00:00.000Z",
      "version": "2023-07-06T08:27:31.407Z",
      "partitionNumber": 0,
      "size": 678723,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T08:00:00.000Z/2023-07-06T09:00:00.000Z",
      "version": "2023-07-06T08:27:31.407Z",
      "partitionNumber": 1,
      "size": 1437866,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T10:00:00.000Z/2023-07-06T11:00:00.000Z",
      "version": "2023-07-06T10:02:42.079Z",
      "partitionNumber": 0,
      "size": 1671296,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T11:00:00.000Z/2023-07-06T12:00:00.000Z",
      "version": "2023-07-06T11:27:23.902Z",
      "partitionNumber": 0,
      "size": 574893,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T11:00:00.000Z/2023-07-06T12:00:00.000Z",
      "version": "2023-07-06T11:27:23.902Z",
      "partitionNumber": 1,
      "size": 1427384,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T12:00:00.000Z/2023-07-06T13:00:00.000Z",
      "version": "2023-07-06T12:52:00.846Z",
      "partitionNumber": 0,
      "size": 2115172,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T14:00:00.000Z/2023-07-06T15:00:00.000Z",
      "version": "2023-07-06T14:32:33.926Z",
      "partitionNumber": 0,
      "size": 589108,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T14:00:00.000Z/2023-07-06T15:00:00.000Z",
      "version": "2023-07-06T14:32:33.926Z",
      "partitionNumber": 1,
      "size": 1392649,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T15:00:00.000Z/2023-07-06T16:00:00.000Z",
      "version": "2023-07-06T15:53:25.467Z",
      "partitionNumber": 0,
      "size": 2037851,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T16:00:00.000Z/2023-07-06T17:00:00.000Z",
      "version": "2023-07-06T16:02:26.568Z",
      "partitionNumber": 0,
      "size": 230400650,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T16:00:00.000Z/2023-07-06T17:00:00.000Z",
      "version": "2023-07-06T16:02:26.568Z",
      "partitionNumber": 1,
      "size": 38209056,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  },
  {
      "interval": "2023-07-06T17:00:00.000Z/2023-07-06T18:00:00.000Z",
      "version": "2023-07-06T17:00:02.391Z",
      "partitionNumber": 0,
      "size": 211099463,
      "locations": [
          {
              "name": "localhost:8083",
              "host": "localhost:8083",
              "hostAndTlsPort": null,
              "maxSize": 300000000000,
              "type": "historical",
              "tier": "_default_tier",
              "priority": 0
          }
      ]
  }
]

더 알아보기 (Learn more)

  • 네이티브 쿼리 타입의 전체 목록은 native queries 문서를 참고하세요.
  • SQL을 사용하고 싶다면 Druid SQL 문서를 확인해 보세요.