SPATH 명령어
SPATH 명령어
spath 명령어는 구조화된 JSON 데이터에서 필드를 추출해요. 경로(path) 기반 모드와 자동 추출(auto-extract) 모드 두 가지로 동작해요.
출처: 문서
본문
spath 명령어는 구조화된 JSON 데이터에서 필드를 추출해요. 두 가지 모드로 동작해요:
- 경로 기반 모드 (Path-based mode) :
path를 지정하면 해당 JSON 경로의 단일 값을 추출해요. - 자동 추출 모드 (Auto-extract mode, 실험적) :
path를 생략하면 JSON의 모든 필드를 map으로 추출해요.
spath 명령어는 OpenSearch 데이터 노드에서 실행되지 않아요. 데이터가 코디네이팅(coordinating) 노드로 반환된 후에 필드를 추출하므로, 대용량 데이터셋에서는 느려요. 중첩 필드를 spath로 필터링하기보다는, 필터링에 필요한 필드를 직접 인덱싱할 것을 권장해요.
구문 (Syntax)
spath 명령어의 구문은 다음과 같아요:
spath input=<field> [output=<field>] [[path=]<path>]
매개변수 (Parameters)
spath 명령어는 다음 매개변수를 지원해요.
| 매개변수 | 필수/선택 | 설명 |
|---|---|---|
input |
필수 | 파싱할 JSON 데이터가 들어 있는 필드예요. |
output |
선택 | 추출한 데이터가 저장될 대상 필드예요. 경로 기반 모드에서는 기본값이 path의 값이고, 자동 추출 모드에서는 input의 값이에요. |
path |
선택 | 추출할 데이터를 식별하는 JSON 경로예요. 생략하면 모든 필드가 map으로 추출돼요 (자동 추출 모드). |
경로 구문에 대한 자세한 내용은 json_extract를 참고해요.
자동 추출 모드 (실험적)
path를 생략하면 spath 명령어는 자동 추출 모드로 실행돼요. 단일 값을 추출하는 대신, 다음 규칙을 사용해 전체 JSON을 map<string, string> 컬럼으로 평탄화(flatten)해요:
- 중첩 객체는 점 표기(dotted) 키를 사용해요:
user.name,user.age - 배열은
{}접미사를 사용해요:tags{},users{}.name - 중복되는 논리 키는 배열로 병합돼요:
c{}.b = [2, 3] - null 값은 보존돼요: JSON의 null은 map에서 문자열
"null"이 돼요 - 모든 값은 문자열로 변환돼요: 숫자와 불리언 값이 문자열 표현으로 변환돼요 (예:
30은"30"이 되고,true는"true"가 되며, 배열은"[a, b, c]"가 돼요)
자동 추출 모드는 문자 수 제한 없이 전체 입력 필드를 처리해요. 대용량 JSON 페이로드라면 특정 필드를 겨냥한 경로 기반 추출을 고려해 보세요.
유효하지 않거나 형식이 잘못된 JSON은 오류가 발생하기 전까지 성공적으로 파싱된 필드를 포함한 부분 결과를 반환해요. 빈 JSON 객체({})는 빈 map을 반환해요.
예제 1: 기본 필드 추출하기
spath의 기본 사용법은 JSON 데이터에서 단일 필드를 추출하는 것이에요. 다음 쿼리는 doc_n 필드의 JSON 객체에서 n 필드를 추출해요:
source=structured
| spath input=doc_n n
| fields doc_n n
쿼리는 다음과 같은 결과를 반환해요:
doc_n | n
{"n": 1} | 1
{"n": 2} | 2
{"n": 3} | 3
예제 2: 리스트와 중첩
다음 쿼리는 중첩 필드를 탐색하고 리스트 요소를 추출하는 방법을 보여줘요:
source=structured
| spath input=doc_list output=first_element list{0}
| spath input=doc_list output=all_elements list{}
| spath input=doc_list output=nested nest_out.nest_in
| fields doc_list first_element all_elements nested
쿼리는 다음과 같은 결과를 반환해요:
doc_list | first_element | all_elements | nested
{"list": [1, 2, 3, 4], "nest_out": {"nest_in": "a"}} | 1 | [1,2,3,4] | a
{"list": [], "nest_out": {"nest_in": "a"}} | null | [] | a
{"list": [5, 6], "nest_out": {"nest_in": "a"}} | 5 | [5,6] | a
예제 3: 내부 요소 합산하기
다음 쿼리는 spath를 사용해 JSON 데이터에서 n 필드를 추출하고 추출된 모든 값의 합을 계산하는 방법을 보여줘요:
source=structured
| spath input=doc_n n
| eval n=cast(n as int)
| stats sum(n)
| fields `sum(n)`
쿼리는 다음과 같은 결과를 반환해요. spath 명령어는 항상 내부 값을 문자열로 반환해요:
sum(n)
6
예제 4: 이스케이프된 경로 사용하기
공백, 점 또는 기타 특수 문자가 포함된 JSON 필드 이름에 접근하려면 따옴표 문자열 구문을 사용해요:
source=structured
| spath output=a input=doc_escape "['a fancy field name']"
| spath output=b input=doc_escape "['a.b.c']"
| fields a b
쿼리는 다음과 같은 결과를 반환해요:
a | b
true | 0
true | 1
false | 2
예제 5: 자동 추출 모드 사용하기
path를 생략하면 spath가 JSON의 모든 필드를 map으로 추출해요. 점 경로 내비게이션을 사용해 개별 값에 접근할 수 있는데, doc.user.name은 map 키 user.name으로 해석돼요. {} 같은 특수 문자가 포함된 키는 백틱(backtick)으로 감싸서 사용해요:
source=structured
| spath input=doc_auto output=doc
| fields doc_auto, doc.user.name, doc.user.age, doc.`tags{}`, doc.active
쿼리는 다음과 같은 결과를 반환해요:
doc_auto | doc.user.name | doc.user.age | doc.tags{} | doc.active
{"user":{"name":"John","age":30},"tags":["java","sql"],"active":true} | John | 30 | [java, sql] | true
{"user":{"name":"Jane","age":25},"tags":["python"],"active":null} | Jane | 25 | python | null
{"user":{"name":"Bob","age":35},"tags":["go","rust","sql"],"user.name":"Bobby"} | [Bob, Bobby] | 35 | [go, rust, sql] | null
이 예제에서 확인할 수 있는 평탄화 규칙은 다음과 같아요:
- 중첩 객체는 점 표기 키를 사용해요:
{"user": {"name": "John", "age": 30}}에서user.name과user.age가 추출돼요 - 배열은
{}접미사를 사용해요:{"tags": ["java", "sql"]}에서tags{}가 추출돼요 - 중복되는 논리 키는 배열로 병합돼요: 세 번째 행에서
"user": {"name": "Bob"}(중첩)과"user.name": "Bobby"(직접 점 키)가 같은 키user.name으로 해석되므로 값이'[Bob, Bobby]'로 병합돼요 - 모든 값은 문자열이에요: 숫자
30은'30'이 되고, 불리언true는'true'가 되며, 배열은'[java, sql]'같은 문자열이 돼요 - null 값은 보존돼요: 두 번째 행에서
"active": null은 map에서'active': 'null'로 유지돼요