JSON 인덱스
JSON 인덱스 (JSON Index)
Apache Pinot용 JSON 인덱스 구성에 대해 설명해요.
출처: 문서
본문
JSON 인덱스는 JSON 문자열 컬럼에 적용되어 그 컬럼의 값 조회와 필터링을 가속화할 수 있어요.
JSON 인덱스를 언제 사용하나
JSON 문자열은 고정 스키마를 강제하지 않고 배열, 맵, 중첩 필드를 나타내는 데 사용될 수 있어요. JSON 문자열은 유연하지만 JSON 문자열 컬럼에 대한 필터링은 비싸므로 사용 사례를 고려하세요.
person 컬럼에 저장된 다음 샘플 레코드와 유사한 일부 JSON 레코드가 있다고 가정해 봐요.
{
"name": "adam",
"age": 30,
"country": "us",
"addresses":
[
{
"number" : 112,
"street" : "main st",
"country" : "us"
},
{
"number" : 2,
"street" : "second st",
"country" : "us"
},
{
"number" : 3,
"street" : "third st",
"country" : "ca"
}
]
}
인덱스 없이 키를 조회하고 값에 따라 레코드를 필터링하려면 Pinot는 모든 레코드에 대해 JSON 문자열에서 JSON 객체를 스캔하고 재구성한 다음 키를 조회하고 값을 비교해야 해요.
예를 들어 name이 "adam"인 모든 사람을 찾으려면 쿼리는 다음과 같아요.
SELECT *
FROM mytable
WHERE JSON_EXTRACT_SCALAR(person, '$.name', 'STRING') = 'adam'
JSON 인덱스는 모든 JSON 객체를 스캔하고 재구성하지 않고도 JSON 문자열 컬럼에 대한 필터링을 가속화하도록 설계됐어요.
지원 컬럼 유형
JSON 인덱스는 STRING과 MAP 컬럼(단일 값만)에서 지원돼요. JSON 컬럼은 높은 카디널리티를 가지는 경향이 있으므로 보통 noDictionaryColumns와 함께 사용돼요.
JSON 인덱스 활성화 및 구성
테이블 구성에서 다음 옵션을 구성해 JSON 인덱스를 활성화할 수 있어요.
| Config Key | Description | Type | Default |
|---|---|---|---|
| maxLevels | json 객체를 펼칠(flatten) 최대 수준(array도 한 수준으로 계산). | int | -1 (무제한) |
| excludeArray | 객체를 펼칠 때 array를 제외할지 여부. | boolean | false (array 포함) |
| disableCrossArrayUnnest | 여러 배열을 언네스트하지 않을지 여부(그 배열들의 모든 요소의 고유 조합). 두 배열이 각각 M, N개의 요소를 가지면 펼치기에서 M*N 문서가 생성됨. 그 조합 수가 100k에 도달하면 "Got too many combinations" 메시지로 오류. | boolean | false (모든 요소의 고유 조합 계산) |
| includePaths | 주어진 경로만 포함, 예: "$.a.b", "$.a.c[*]"(excludePaths와 상호 배타). 포함된 경로 아래의 경로도 포함됨, 예: "$.a.b"를 포함하도록 구성되면 "$.a.b.c"가 포함됨. |
Set | null (모든 경로 포함) |
| excludePaths | 주어진 경로 제외, 예: "$.a.b", "$.a.c[*]"(includePaths와 상호 배타). 제외된 경로 아래의 경로도 제외됨. |
Set | null (모든 경로 포함) |
| excludeFields | 주어진 필드 제외, 예: "b", "c", 포함된 경로 아래라도. |
Set | null (모든 필드 포함) |
| indexPaths | 주어진 경로를 인덱싱, 예: *.*, a.**. 인덱싱된 경로와 일치하는 경로가 인덱싱됨, 예: a.**는 첫 번째 레이어가 "a"인 모든 것을 인덱싱, *.*는 maxLevels=2인 모든 것을 인덱싱. 이 구성은 includePaths, excludePaths, maxLevels 등 다른 구성과 함께 동작할 수 있지만 일반적으로 필요하지 않음. |
Set | **와 동등한 null(모든 필드 포함) |
| maxValueLength | json 노드(전체 문서 아님)의 값이 주어진 값보다 길면 인덱싱 전에 $SKIPPED$로 대체. |
int | 0 (비활성) |
| maxBytesSize | 실시간 수집 중 사용되는 변경 가능한 JSON 인덱스의 근사 on-heap 바이트 예산. 추적된 크기가 이 한도에 도달하면 Pinot는 변경 가능한 JSON 인덱스 성장을 중지. 포스팅 목록은 제외하므로 정확한 상한보다 실용적 가드레일로 사용. | long | null (제한 없음) |
| skipInvalidJson | 설정되면 json을 인덱스에 추가할 때 예외를 던지는 대신 잘못된 형식의 json을 빈 키/경로와 $SKIPPED$ 값으로 대체. |
boolean | false (비활성) |
maxBytesSize는 크거나 매우 다양한 JSON 문서를 수집하는 실시간 테이블에 가장 유용해요. 변경 가능한 JSON 인덱스의 힙 성장을 제한하고 예기치 않게 큰 세그먼트가 구축될 위험을 줄이는 데 도움이 돼요.
권장 구성 방법
JSON 인덱스를 구성하는 권장 방법은 fieldConfigList.indexes 객체의 json 키 안에 두는 것이에요.
{
"fieldConfigList": [
{
"name": "person",
"indexes": {
"json": {
"maxLevels": 2,
"excludeArray": false,
"disableCrossArrayUnnest": true,
"maxBytesSize": 134217728,
"includePaths": null,
"excludePaths": null,
"excludeFields": null,
"indexPaths": null
}
}
}
],
...
}
모든 옵션은 선택적이므로 다음은 기본 파라미터 값을 사용하는 유효한 구성이에요.
{
"fieldConfigList": [
{
"name": "person",
"indexes": {
"json": {}
}
}
],
...
}
더 이상 사용되지 않는 JSON 인덱스 구성 방법
테이블 구성 내 tableIndexConfig 섹션에서 구성할 수 있는 이전 방식이 두 가지 있어요.
첫 번째는 위에서 설명한 것과 같은 JSON을 사용하지만 tableIndexConfig.jsonIndexConfigs.<column name> 안에 정의돼요.
{
"tableIndexConfig": {
"jsonIndexConfigs": {
"person": {
"maxLevels": 2,
"excludeArray": false,
"disableCrossArrayUnnest": true,
"includePaths": null,
"excludePaths": null,
"excludeFields": null,
"indexPaths": null
},
...
},
...
}
}
이전 경우처럼 모든 파라미터는 선택적이므로 다음도 유효해요.
{
"tableIndexConfig": {
"jsonIndexConfigs": {
"person": {},
...
},
...
}
}
마지막 옵션은 어떤 파라미터도 구성할 수 없어요. 이 옵션을 사용하려면 이 예시처럼 tableIndexConfig.jsonIndexColumns에 컬럼 이름을 추가하세요.
{
"tableIndexConfig": {
"jsonIndexColumns": [
"person",
...
],
...
}
}
예시:
다음 JSON 문서를 사용해요.
{
"name": "adam",
"age": 20,
"addresses": [
{
"country": "us",
"street": "main st",
"number": 1
},
{
"country": "ca",
"street": "second st",
"number": 2
}
],
"skills": [
"english",
"programming"
]
}
기본 설정을 사용하면 문서를 다음 레코드로 펼칩니다.
{
"name": "adam",
"age": 20,
"addresses[0].country": "us",
"addresses[0].street": "main st",
"addresses[0].number": 1,
"skills[0]": "english"
},
{
"name": "adam",
"age": 20,
"addresses[0].country": "us",
"addresses[0].street": "main st",
"addresses[0].number": 1,
"skills[1]": "programming"
},
{
"name": "adam",
"age": 20,
"addresses[1].country": "ca",
"addresses[1].street": "second st",
"addresses[1].number": 2,
"skills[0]": "english"
},
{
"name": "adam",
"age": 20,
"addresses[1].country": "ca",
"addresses[1].street": "second st",
"addresses[1].number": 2,
"skills[1]": "programming"
}
maxValueLength을 9로 설정하면:
{
"name": "adam",
"age": 20,
"addresses[0].country": "us",
"addresses[0].street": "main st",
"addresses[0].number": 1,
"skills[0]": "english"
},
{
"name": "adam",
"age": 20,
"addresses[0].country": "us",
"addresses[0].street": "main st",
"addresses[0].number": 1,
"skills[1]": "$SKIPPED$"
},
...
maxLevels를 1로 설정하면:
{
"name": "adam",
"age": 20
}
maxLevels를 2로 설정하면:
{
"name": "adam",
"age": 20,
"skills[0]": "english"
},
{
"name": "adam",
"age": 20,
"skills[1]": "programming"
}
excludeArray를 true로 설정하면:
{
"name": "adam",
"age": 20
}
disableCrossArrayUnnest를 true로 설정하면 JSON 펼치기 중 생성되는 문서 수는 모든 배열 크기의 합이에요(위 예시에서 2+2 = 4).
disableCrossArrayUnnest를 false로 설정하면 JSON 펼치기 중 생성되는 문서 수는 모든 배열 크기의 곱이에요(위 예시에서 2*2 = 4). JSON이 여러 개의 큰 중첩 배열을 포함하면 100k 펼쳐진 문서 한도를 피하고 'Got too many combinations' 오류를 트리거하지 않도록 교차 배열 언네스트를 비활성화(disableCrossArrayUnnest=true)해야 할 수 있어요.
includePaths를 ["$.name", "$.addresses[*].country"]로 설정하면:
{
"name": "adam",
"addresses[0].country": "us"
},
{
"name": "adam",
"addresses[1].country": "ca"
}
excludePaths를 ["$.age", "$.addresses[*].number"]로 설정하면 age와 각 주소의 number 필드가 결과에서 제외돼요.
excludeFields를 ["age", "street"]로 설정하면 age와 모든 street 필드가 결과에서 제외돼요.
indexPaths를 ["*", "address..country"]로 설정하면 다른 경로는 무시하고 지정된 경로만 인덱싱돼요.
skipInvalidJson을 true로 설정하면 원본 JSON을 손상시켜도(예: { _invalid_json_ ... }) 펼치기가 다음을 생성해요.
{ "": "$SKIPPED$" }
JSON 인덱스는 값이 JSON 문자열인 STRING/JSON 컬럼에만 적용될 수 있다는 점을 유의하세요.
JSON 인덱스를 사용할 때 불필요한 저장 오버헤드를 줄이려면 인덱스된 컬럼을
noDictionaryColumns목록에 추가할 것을 권장해요. 그 구성 속성에 대한 지침은 Raw value forward index 문서를 참조하세요.
JSON 인덱스 사용 방법
JSON 인덱스는 필터링을 위해 JSON_MATCH 조건자로 사용될 수 있어요: JSON_MATCH(<column>, '<filterExpression>'). 예를 들어 name이 "adam"인 모든 항목을 찾으려면:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.name"=''adam''')
필터 표현식 안의 따옴표는 이스케이프해야 한다는 점에 유의하세요.
JSON 인덱스는 값 추출용 JSON_EXTRACT_INDEX 조건자로도 사용될 수 있어요(선택적으로 필터링): JSON_EXTRACT_INDEX(<column>, '<jsonPath>', ['resultsType'], ['filter']). 예를 들어 $.id 경로가 10 미만일 때 $.name 경로의 모든 값을 추출하려면:
SELECT jsonextractindex(repo, '$.name', 'STRING', 'dummyValue', '"$.id" < 10')
FROM mytable
더 심층적인 예시는 JSON_EXTRACT_INDEX function documentation에서 찾을 수 있어요.
지원되는 필터 표현식
단순 키 조회
name이 "adam"인 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.name"=''adam''')
또는
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.name" IN (''adam'')')
체인 키 조회
number가 112인 주소(주소 중 하나)를 가진 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].number"=112')
미국에 없는 주소가 하나 이상 있는 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].country" != ''us''')
또는
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].country" NOT IN (''us'') ')
정규식 기반 조회
street가 'st'라는 용어를 포함하는 주소(주소 중 하나)를 가진 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, 'REGEXP_LIKE("$.addresses[*].street", ''.*st.*'')')
범위 조회
나이가 18보다 큰 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.age" > 18')
나이가 20과 40 사이(포함)인 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.age" BETWEEN 20 AND 40')
중첩 필터 표현식
name이 "adam"이고 number가 112인 주소(주소 중 하나)도 가진 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.name"=''adam'' AND "$.addresses[*].number"=112')
NOT IN과!=는 Pinot 1.2.0보다 이전 버전의 중첩 필터 표현식에서 사용할 수 없어요.IS NULL은 현재 중첩 필터 표현식에서 사용할 수 없다는 점에 유의하세요.
배열 접근
첫 번째 주소의 number가 112인 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[0].number"=112')
JSON 인덱스는 펼쳐진 JSON 문서를 기반으로 동작하므로, 교차 배열 언네스팅이 비활성화되면( disableCrossArrayUnnest = true ) 단일 JSON_MATCH 함수 호출에서 둘 이상의 배열을 조회하면 빈 결과가 반환돼요, 예:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].country"=''us'' AND "$.skills[*]"=''english''')
이런 경우 표현식을 여러 JSON_MATCH 호출로 나눠야 해요, 예:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].country"=''us''')
AND JSON_MATCH(person, '"$.skills[*]"=''english''')
존재 확인
JSON 내에 phone 필드가 있는 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.phone" IS NOT NULL')
첫 번째 주소에 JSON 내 floor 필드가 포함되지 않은 모든 사람 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[0].floor" IS NULL')
JSON 컨텍스트 유지
배열 내 객체 요소에 대해 JSON 컨텍스트가 유지되므로, 필터가 배열의 다른 객체를 교차 대응시키지 않아요.
"ca"에 있는 "main st"에 사는 모든 사람을 찾으려면:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].street"=''main st'' AND "$.addresses[*].country"=''ca''')
이 쿼리는 "adam"과 일치하지 않는데, 그의 주소 중 street와 country를 모두 일치시키는 주소가 없기 때문이에요.
JSON 컨텍스트를 원하지 않으면 여러 개의 별도 JSON_MATCH 조건자를 사용하세요. 예를 들어 "main st"에 주소가 있고 "ca"에 주소가 있는(일치가 같은 주소일 필요는 없는) 모든 사람을 찾으려면:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[*].street"=''main st''')
AND JSON_MATCH(person, '"$.addresses[*].country"=''ca''')
이 쿼리는 "adam"과 일치하는데, 그의 주소 중 하나가 street와 일치하고 다른 하나가 country와 일치하기 때문이에요.
배열 인덱스는 요소 내 별도 항목으로 유지되므로, 배열 내 다른 요소를 조회하려면 여러 JSON_MATCH 조건자가 필요해요. 예를 들어 첫 번째 주소가 "main st"에 있고 두 번째 주소가 "second st"에 있는 모든 사람을 찾으려면:
SELECT ...
FROM mytable
WHERE JSON_MATCH(person, '"$.addresses[0].street"=''main st''')
AND JSON_MATCH(person, '"$.addresses[1].street"=''second st''')
지원되는 JSON 값
Object
위의 예시 참조.
Array
["item1", "item2", "item3"]
"arrayCol"에서 배열 요소 "item1"이 있는 레코드 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(arrayCol, '"$[*]"=''item1''')
"arrayCol"에서 두 번째 배열 요소 "item2"가 있는 레코드 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(arrayCol, '"$[1]"=''item2''')
Value
123
1.23
"Hello World"
"valueCol"에서 값 123이 있는 레코드 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(valueCol, '"$"=123')
Null
null
"nullableCol"에 null이 있는 레코드 찾기:
SELECT ...
FROM mytable
WHERE JSON_MATCH(nullableCol, '"$" IS NULL')
SELECT DISTINCT 가속화
JSON 인덱스가 구성되면 JSON 컬럼의 SELECT DISTINCT 쿼리에 인덱스 전용 실행 경로를 사용할 수 있어요. 프로젝션과 변환 파이프라인을 통해 문서를 스캔하는 대신 연산자가 JSON 인덱스의 내부 값→docId 맵에서 직접 고유 값을 읽어 문서별 평가를 완전히 피해요.
이 기능은 opt-in이며 쿼리 옵션으로 활성화해야 해요.
활성화 방법
useIndexBasedDistinctOperator 쿼리 옵션을 true로 설정하세요.
SET useIndexBasedDistinctOperator = true;
SELECT DISTINCT jsonExtractIndex(person, '$.name', 'STRING')
FROM mytable
ORDER BY jsonExtractIndex(person, '$.name', 'STRING')
LIMIT 1000;
REST API로 쿼리별 활성화할 수도 있어요.
POST /query/sql
{
"sql": "SELECT DISTINCT jsonExtractIndex(person, '$.name', 'STRING') FROM mytable",
"queryOptions": "useIndexBasedDistinctOperator=true"
}
지원 쿼리 패턴
| Pattern | Supported |
|---|---|
SELECT DISTINCT jsonExtractIndex(col, '$.path', 'STRING') |
Yes |
SELECT DISTINCT jsonExtractIndex(col, '$.path', 'INT') |
Yes (all single-value types) |
SELECT DISTINCT jsonExtractIndex(col, '$.path', 'STRING', 'default') |
Yes (with default value) |
SELECT DISTINCT jsonExtractIndex(col, '$.path', 'STRING', 'default', '"$.otherPath" = ''value''') |
Yes (with 5-arg JSON filter pushdown) |
With WHERE clause filters |
Yes |
With WHERE JSON_MATCH(...) |
Yes |
With ORDER BY |
Yes |
Multi-value types (STRING_ARRAY, etc.) |
Yes (array elements are flattened into scalar DISTINCT rows) |
Multiple columns in SELECT DISTINCT |
No (falls back to default execution) |
지원되지 않는 쿼리 패턴이면 쿼리는 기본 실행 경로로 여전히 올바르게 실행돼요.
5-arg 필터 푸시다운 및 누락-경로 동작
jsonExtractIndex의 5-arg 형식은 JSON 필터 표현식을 JSON 인덱스 조회 자체로 푸시해요.
SET useIndexBasedDistinctOperator = true;
SELECT DISTINCT jsonExtractIndex(
person,
'$.country',
'STRING',
'missing',
'"$.status" = ''active'''
)
FROM mytable
ORDER BY jsonExtractIndex(person, '$.country', 'STRING', 'missing', '"$.status" = ''active''')
LIMIT 1000;
이 필터 표현식은 JSON_MATCH와 같은 문법을 사용하지만 Pinot가 DISTINCT 값을 구체화하기 전에 JSON 인덱스 조회 내에서 실행돼요. 추출된 경로나 다른 인덱싱된 JSON 경로로 필터링할 수 있어요. WHERE JSON_MATCH(...)를 포함한 일반 WHERE 필터는 여전히 동작하며 Pinot가 인덱스 적중을 행 수준 doc ID로 변환한 후 적용돼요.
인덱스 기반 DISTINCT의 누락-경로 처리는 스캔 기반 jsonExtractIndex(...)와 일치해요.
- 4-arg 기본값이 있으면 일치하는 문서가 추출된 경로를 포함하지 않을 때 기본값을 추가해요.
- 기본값 없이
enableNullHandling=true면 Pinot는NULL을 추가해요. - 기본값 없이 null 처리가 없으면 Pinot는
Illegal Json Path를 던져요.
DISTINCT 결과에 JSON 인덱스 조회가 반환한 값만 포함되게 하려면 useIndexBasedDistinctOperator=true와 함께 jsonIndexDistinctSkipMissingPath=true를 설정하세요. 그러면 누락 문서에 대한 기본값, NULL, Illegal Json Path 동작이 억제돼요.
사전 요구 사항
컬럼에 테이블 구성에서 JSON 인덱스가 구성되어 있어야 해요. 구성 지침은 Enable and configure a JSON index를 참조하세요.
jsonExtractIndex에 사용된 JSON 경로가 인덱스에 포함되어야 해요. includePaths나 indexPaths로 인덱싱된 경로를 제한했다면 조회하는 경로가 커버되는지 확인하세요.
사용 확인 방법
EXPLAIN PLAN FOR를 사용하고 계획에서 DISTINCT_JSON_INDEX(...)를 찾아보세요.
쿼리 통계에서 numDocsScanned은 행 수준 필터를 통과한 문서 수(필터 없으면 총 문서 수)를 반영하고, numEntriesScannedPostFilter는 연산자가 조사한 JSON-인덱스 값 수를 반영해요. 0이 아닌 numEntriesScannedPostFilter가 쿼리가 대체 경로로 갔다는 뜻은 아니에요.
Pinot가 기본 실행 경로로 대체된다면 다음을 확인하세요.
- 쿼리 옵션
useIndexBasedDistinctOperator가true로 설정되어 있는지 - 컬럼에 JSON 인덱스가 구성되어 있는지
- 쿼리가 지원 패턴(
jsonExtractIndex에 대한 단일SELECT DISTINCT표현식)을 사용하는지
성능 혜택
인덱스 기반 distinct 연산자는 모든 문서를 스캔하고 평가하지 않아요. 대신 JSON 인덱스 구조에서 직접 고유 값을 읽어요. 이는 고유 값 수가 전체 문서 수보다 훨씬 작은 높은 카디널리티 JSON 컬럼과 큰 테이블에 상당한 성능 개선을 제공해요.
SELECT DISTINCT 가속화의 제한 사항
- 이 기능은 기본적으로 비활성화되어 있으며
useIndexBasedDistinctOperator쿼리 옵션으로 활성화해야 해요. - 단일 컬럼
SELECT DISTINCT쿼리만 지원돼요.DISTINCT절에 여러 컬럼이 있는 쿼리는 기본 실행 경로로 대체돼요. _ARRAY결과 유형은 지원되지만 Pinot는 배열 요소를 스칼라 DISTINCT 행으로 펼쳐요.- 이 최적화의 혜택을 받으려면 쿼리가
jsonExtractIndex(JSON_EXTRACT_SCALAR아님)를 사용해야 해요.
성능 팁
인덱스 기반 DISTINCT 쿼리
JSON 인덱스가 있는 JSON 경로에서 SELECT DISTINCT를 자주 실행한다면 useIndexBasedDistinctOperator를 활성화해 문서 스캔을 완전히 건너뛰세요.
SET useIndexBasedDistinctOperator = true;
SELECT DISTINCT jsonExtractIndex(col, '$.path', 'STRING') FROM myTable;
이렇게 하면 작업이 프로젝션/변환 경로 대신 JSON 인덱스 경로에 유지되고, numEntriesScannedPostFilter는 Pinot가 조사한 distinct 인덱스 값만 추적해요.
DISTINCT 필터링을 JSON 인덱스로 푸시
적용할 JSON 조건자를 이미 안다면 5-arg jsonExtractIndex(..., defaultValue, jsonFilterExpression) 형식을 사용해 Pinot가 그 필터를 JSON 인덱스 조회 내에서 적용할 수 있게 하세요.
SET useIndexBasedDistinctOperator = true;
SELECT DISTINCT jsonExtractIndex(
person,
'$.country',
'STRING',
'missing',
'"$.country" IN (''us'', ''ca'')'
)
FROM mytable;
푸시다운된 필터 밖의 문서가 기본값, NULL, Illegal Json Path에 기여하지 않게 하려면 쿼리 전에 SET jsonIndexDistinctSkipMissingPath = true;를 추가하세요.
제한 사항
- 필터 표현식의 키(왼쪽)는 JSON 객체의 리프 수준이어야 해요. 예를 들어
"$.addresses[*]"='main st'는 동작하지 않아요.