jsonextractscalar

jsonextractscalar

JSONEXTRACTSCALAR 함수는 jsonField에서 'jsonPath'를 평가하고 해석된 값을 요청한 'resultsType'으로 강제 변환하는 함수예요. 경로가 없거나, null이거나, 파싱 실패가 쿼리를 실패시키지 않아야 하는 경우 선택적 defaultValue를 사용해요.

출처: 문서

본문

jsonField에서 'jsonPath'를 평가하고 해석된 값을 요청한 'resultsType'으로 강제 변환해요. 경로가 없거나, null이거나, 파싱 실패가 쿼리를 실패시키지 않아야 하는 경우 선택적 defaultValue를 사용해요.

시그니처 (Signature)

JSONEXTRACTSCALAR(jsonField, 'jsonPath', 'resultsType', [defaultValue])

Arguments Description
jsonField JSON 문서를 포함하는 Identifier/Expression
'jsonPath' JSON 문서에서 값을 읽기 위해 JsonPath 문법을 따름
'resultsType' 지원되는 Pinot 결과 타입. 일반적인 쿼리 지향 타입은 INT, LONG, FLOAT, DOUBLE, BIG_DECIMAL, BOOLEAN, TIMESTAMP, STRING이에요. 다중 값 결과에는 INT_ARRAY, STRING_ARRAY, BIG_DECIMAL_ARRAY처럼 _ARRAY를 붙이세요.

'jsonPath'과 `` **'resultsType'`은 리터럴이에요.** Pinot은 이를 식별자와 구분하기 위해 작은따옴표를 사용해요.

빠른 변형 (Fast variants)

추출이 쿼리나 수집 변환의 핫 경로일 때 JSONEXTRACTSCALARFAST 또는 JSONEXTRACTSCALARFIRSTMATCH를 사용하세요. 두 변형 모두 JSONEXTRACTSCALAR와 동일한 인자, 결과 타입, 기본값, 강제 변환 규칙을 사용해요.

스트리밍 최적화는 단순 선형 경로, 즉 $ 뒤에 .key, ['key'], 또는 [index] 세그먼트만 이어지는 경로에 적용돼요. 와일드카드, 재귀 하강, 필터, 유니온, 슬라이스, 음수 인덱스 및 기타 지원되지 않는 경로는 자동으로 기존 Jayway 구현을 사용해요.

JSONEXTRACTSCALARFORY (실험적)

JSONEXTRACTSCALARFORY(jsonField, 'jsonPath', 'resultsType', [defaultValue])

JSONEXTRACTSCALARFORY는 단순 스칼라 경로에 Apache Fory JSON 파싱을 평가하기 위한 실험적 변형이에요. 전체 문서를 검증하고, 중복 키에 대해 마지막 키가 이기는 동작을 유지하며, 지원되지 않는 경로나 값, BYTES 입력, 깊게 중첩되거나 잘못된 JSON, 런타임 실패에 대해서는 기존 Jackson/Jayway 구현으로 폴백해요.

표준 Pinot 바이너리 배포에는 Fory가 포함되지 않아요. org.apache.fory:fory-json:1.6.0과 그 fory-core 의존성이 애플리케이션 클래스패스에 있지 않는 한, 함수는 사용 가능하지만 항상 호환성 폴백을 사용해요. 이 실험적 함수는 변경되거나 제거될 수 있어요.

JSONEXTRACTSCALARFAST

JSONEXTRACTSCALARFAST(jsonField, 'jsonPath', 'resultsType', [defaultValue])

JSONEXTRACTSCALARFAST는 Jayway 객체 트리를 구체화하지 않고 전체 JSON 루트를 스캔해요. 일반 입력에 대해 더 낮은 할당과 정상적인 JSONEXTRACTSCALAR 의미론(중복 키에 대한 마지막 키가 이기는 동작 포함)을 원할 때 사용하세요. 스트리밍 추출기가 지원하지 않는 경로나 입력에서는 기존 구현으로 폴백해요.

Jayway와 달리 스트리밍 추출기는 주소가 지정되지 않은 하위 트리에서의 구체화 실패(예: 한도를 초과한 문자열이나 병리적인 BIG_DECIMAL 지수)를 피할 수 있어요. 주소가 지정된 경로에 대해 반환되는 값은 변경하지 않아요.

JSONEXTRACTSCALARFIRSTMATCH

JSONEXTRACTSCALARFIRSTMATCH(jsonField, 'jsonPath', 'resultsType', [defaultValue])

JSONEXTRACTSCALARFIRSTMATCH는 주소가 지정된 값을 찾은 후 중지해요. 특히 해당 필드가 대규모 문서에서 일찍 나타날 때 유용해요. 잘 구성되고 중복이 없는 JSON에서만 사용하세요: 중복 키는 첫 번째 비-null 값으로 해석되고, 주소가 지정된 값 이후의 잘못된 내용은 검증되지 않아요.

예를 들어:

SELECT
  jsonExtractScalarFast(payload, '$.user.id', 'LONG', -1) AS user_id,
  jsonExtractScalarFirstMatch(payload, '$.service.name', 'STRING', 'unknown') AS service_name
FROM events
LIMIT 10;

첫 번째 인자는 단일 값 STRING 또는 BYTES 컬럼이거나 변환 표현식이어야 해요. 다단계 플래닝은 같은 결과 타입을 허용하지만, 현재 BIG_DECIMAL_ARRAY를 DOUBLE_ARRAY로 낮춰요. 소수 배열 정밀도가 중요할 때는 단일 단계 엔진을 사용하세요.

사용 예시 (Usage Examples)

이 섹션의 예시는 Batch JSON Quick Start를 기반으로 해요. 특히 WHERE id = 7044874109 행을 쿼리할 거예요:

select repo
from githubEvents 
WHERE id = 7044874109
repo
{"id":115911530,"name":"LimeVista/Tapes","url":"https://api.github.com/repos/LimeVista/Tapes"}

다음 예시는 JSONEXTRACTSCALAR 함수 사용법을 보여줘요:

select id, jsonextractscalar(repo, '$.name', 'STRING') AS name
from githubEvents 
WHERE id = 7044874109
id name
7044874109 LimeVista/Tapes
select id, jsonextractscalar(repo, '$.foo', 'STRING') AS name
from githubEvents 
WHERE id = 7044874109
[
  {
    "message": "QueryExecutionError:\njava.lang.RuntimeException: Illegal Json Path: [$.foo], when reading [{\"id\":115911530,\"name\":\"LimeVista/Tapes\",\"url\":\"https://api.github.com/repos/LimeVista/Tapes\"}]\n\tat org.apache.pinot.core.operator.transform.function.JsonExtractScalarTransformFunction.transformToStringValuesSV(JsonExtractScalarTransformFunction.java:254)\n\tat org.apache.pinot.core.operator.docvalsets.TransformBlockValSet.getStringValuesSV(TransformBlockValSet.java:90)\n\tat org.apache.pinot.core.common.RowBasedBlockValueFetcher.createFetcher(RowBasedBlockValueFetcher.java:64)\n\tat org.apache.pinot.core.common.RowBasedBlockValueFetcher.<init>(RowBasedBlockValueFetcher.java:32)",
    "errorCode": 200
  }
]
select id, jsonextractscalar(repo, '$.foo', 'STRING', 'dummyValue') AS name
from githubEvents 
WHERE id = 7044874109
id name
7044874109 dummyValue

결과 타입 지정과 강제 변환 (Result typing and coercion)

JSONEXTRACTSCALAR는 이제 JsonPath를 해석한 후 Pinot이 적용하는 값별 강제 변환 규칙을 문서화해요. resultsType을 선택할 때 의존할 수 있는 사용자 대면 동작이에요:

  • BIG_DECIMAL과 BIG_DECIMAL_ARRAY는 DOUBLE을 거치지 않고 JSON 숫자 정밀도를 보존해요. JSON 페이로드가 고정밀 소수 값을 포함할 수 있다면 이 결과 타입을 사용하세요.
  • STRING과 STRING_ARRAY는 JSON 문자열을 그대로 반환해요. 숫자, 불리언, 배열, 객체의 경우 Pinot은 해석된 JSON 값을 간결한 JSON 텍스트로 직렬화해요.
  • 숫자 결과 타입은 각 해석된 값을 독립적으로 강제 변환해요. 즉 [1, "2", true] 같은 배열을 INT_ARRAY로 읽을 수 있고, Pinot은 요소를 1, 2, 1로 변환해요.
  • BOOLEAN과 BOOLEAN_ARRAY는 Pinot의 불리언 강제 변환 규칙을 따르며, 0이 아닌 숫자는 true, 0은 false이고 "true" 또는 "1" 같은 문자열도 true로 취급돼요.
  • TIMESTAMP와 TIMESTAMP_ARRAY는 숫자나 문자열 형태의 에포크 밀리초와 ISO-8601 타임스탬프 문자열을 모두 허용해요.

예를 들어, 다음 쿼리는 이제 안전하고 소스 기반이에요:

select jsonextractscalar(payload, '$.prices', 'BIG_DECIMAL_ARRAY') as prices
from myTable

12345678901234567890.123456789 같은 값이 정확한 소수 정밀도를 유지해야 할 때 BIG_DECIMAL_ARRAY를 사용하세요.

select jsonextractscalar(payload, '$.metadata', 'STRING') as metadata_json
from myTable

$.metadata가 JSON 객체나 배열로 해석되면, Pinot은 런타임 캐스트를 실패시키는 대신 {"a":1} 또는 [1,2,3] 같은 간결한 JSON 텍스트를 반환해요.

null 처리 (Null Handling)

Pinot의 null 처리가 활성화되면(SET enableNullHandling = true), 'null' 기본값을 가진 JSONEXTRACTSCALAR의 동작이 향상됐어요:

  • 기본값 매개변수가 명시적으로 'null'로 설정되고 null 처리가 활성화되면, jsonextractscalar는 JSON 경로가 없거나 null 값에 대해 문자열 "null" 대신 SQL NULL을 올바르게 반환해요.
  • 이는 쿼리 결과에서 SQL NULL의 올바른 전파를 허용해 null 의미론과 일관성을 개선해요.

null 처리 예시 (Example with Null Handling)

SET enableNullHandling = true;

select id, jsonextractscalar(repo, '$.missingPath', 'STRING', 'null') AS missingField
from githubEvents 
WHERE id = 7044874109

null 처리가 활성화되면, 결과는 문자열 "null"이 아니라 SQL NULL이 될 거예요:

id missingField
7044874109 (null)

null 처리 없이 또는 null이 아닌 기본값을 사용하면 함수는 이전처럼 동작하며, 지정한 기본값이나 문자열 "null"을 반환해요.

더 알아보기 (Learn more)