검색 요청 시 정의
원본 보기검색 요청 시 정의
검색 요청에 runtime_mappings 섹션을 지정하면 해당 쿼리의 일부로만 존재하는 런타임 필드를 만들 수 있습니다. 매핑에 런타임 필드를 추가할 때와 마찬가지로 runtime_mappings 섹션의 일부로 스크립트를 지정합니다.
검색 요청에서 런타임 필드를 정의하는 형식은 인덱스 매핑에서 런타임 필드를 정의하는 형식과 동일합니다. 인덱스 매핑의 runtime에 있는 필드 정의를 검색 요청의 runtime_mappings 섹션으로 복사하면 됩니다.
다음 검색 요청은 runtime_mappings 섹션에 day_of_week 필드를 추가합니다. 필드 값은 동적으로 계산되며, 이 검색 요청의 컨텍스트 안에서만 유효합니다:
GET my-index-000001/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
"aggs": {
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
}
}
더 나아가 다른 런타임 필드의 값을 반환하는 런타임 필드를 검색 요청에서 정의할 수도 있습니다. 예를 들어 센서 데이터를 벌크 인덱싱했다고 가정해 보겠습니다:
POST my-index-000001/_bulk?refresh=true
{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":"5.2","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":"5.8","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":"5.1","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":"5.6","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":"4.2","start": "400","end":"8625309"}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":"4.0","start": "400","end":"8625309"}}
인덱싱을 마친 뒤에야 숫자 데이터가 text 타입으로 매핑되었다는 것을 알게 되었습니다. measures.start와 measures.end 필드로 집계를 수행하고 싶지만, text 타입 필드로는 집계할 수 없기 때문에 집계가 실패합니다. 이럴 때 런타임 필드가 해결책이 됩니다! 인덱싱된 필드와 같은 이름의 런타임 필드를 추가하고 데이터 타입을 수정할 수 있습니다:
PUT my-index-000001/_mapping
{
"runtime": {
"measures.start": {
"type": "long"
},
"measures.end": {
"type": "long"
}
}
}
런타임 필드는 인덱스 매핑에 정의된 동일한 이름의 필드보다 우선합니다. 이러한 유연성 덕분에 필드 자체를 수정하지 않고도 기존 필드를 가리고 다른 값을 계산할 수 있습니다. 인덱스 매핑에 실수가 있었다면, 런타임 필드를 사용해 검색 요청 중에 매핑의 값을 재정의하는 값을 계산할 수 있습니다.
이제 measures.start와 measures.end 필드에 평균 집계를 손쉽게 실행할 수 있습니다:
GET my-index-000001/_search
{
"aggs": {
"avg_start": {
"avg": {
"field": "measures.start"
}
},
"avg_end": {
"avg": {
"field": "measures.end"
}
}
}
}
응답에는 기반 데이터의 값을 변경하지 않은 채 집계 결과가 포함됩니다:
{
"aggregations" : {
"avg_start" : {
"value" : 333.3333333333333
},
"avg_end" : {
"value" : 8658642.333333334
}
}
}
또한 값을 계산하는 런타임 필드를 검색 쿼리의 일부로 정의한 다음, 같은 쿼리 안에서 그 필드에 통계 집계를 실행할 수 있습니다.
duration 런타임 필드는 인덱스 매핑에 존재하지 않지만, 그래도 해당 필드로 검색하고 집계할 수 있습니다. 다음 쿼리는 duration 필드의 계산된 값을 반환하고, 집계된 문서에서 추출한 숫자 값에 대한 통계를 계산하는 stats 집계를 실행합니다.
GET my-index-000001/_search
{
"runtime_mappings": {
"duration": {
"type": "long",
"script": {
"source": """
emit(doc['measures.end'].value - doc['measures.start'].value);
"""
}
}
},
"aggs": {
"duration_stats": {
"stats": {
"field": "duration"
}
}
}
}
duration 런타임 필드는 검색 쿼리의 컨텍스트 안에서만 존재하지만, 그 필드로 검색하고 집계할 수 있습니다. 이러한 유연성은 매우 강력해서, 인덱스 매핑의 실수를 바로잡고 단일 검색 요청 안에서 계산을 동적으로 완료할 수 있게 해줍니다.
{
"aggregations" : {
"duration_stats" : {
"count" : 6,
"min" : 8624909.0,
"max" : 8675009.0,
"avg" : 8658309.0,
"sum" : 5.1949854E7
}
}
}